0

I have two arrays, how would I get the list of elements that appear exclusively in the second, that are not available in the first?

Array1=( "A" "B" "C" "D" ) Array2=( "B" "E" "G" )

I need the output as Array3=("E" "G") because E and G are not present in Array1. I used @ephemient @SiegeX answers but that is not returning what I need.

function arraydiff() {
   awk 'BEGIN{RS=ORS=" "}
        {NR==FNR?a[$0]++:a[$0]--}
        END{for(k in a)if(a[k])print k}' <(echo -n "${!1}") <(echo -n "${!2}")
}
Array1=( "A" "B" "C" "D" )
Array2=( "B" "E" "G" )
Array3=($(arraydiff Array1[@] Array2[@]))
hmedia1
  • 4,854
  • 2
  • 21
  • 26
Eva
  • 107
  • 10

3 Answers3

5

Use an associative array to store the elements of the first array, and see if elements of the second array appear as keys in it:

#!/usr/bin/env bash

arraydiff() {
    # Use namerefs for the arrays to work around not being to pass
    # two different arrays as function arguments otherwise
    local -n a1=$1 a2=$2
    # Populate an associative array with the elements of the first array
    local -A elems
    local elem
    for elem in "${a1[@]}"; do
        elems[$elem]=1
    done
    # If an element of the second array doesn't appear in the associative
    # array, print it.
    for elem in "${a2[@]}"; do
        if [[ ! -v elems[$elem] ]]; then
            printf "%s\n" "$elem"
        fi
    done
}

declare -a array1=( A B C D ) array2=( B E G )
readarray -t array3 < <(arraydiff array1 array2)
printf "%s\n" "${array3[@]}"
Shawn
  • 38,372
  • 3
  • 13
  • 43
4

Use comm. The following:

comm -13 <(printf "%s\n" "${array1[@]}" | sort) <(printf "%s\n" "${array2[@]}" | sort)

will output E and G. You can then read it to an array with readarray.

KamilCuk
  • 96,430
  • 6
  • 33
  • 74
2

With bash:

#!/bin/bash

array1=( "A" "B" "C" "D" )
array2=( "B" "E" "G" )
array3=("${array2[@]}")

for i in "${array2[@]}"; do
  for j in "${array1[@]}"; do
    [[ "$i" == "$j" ]] && unset array3[$i]
  done
done

array3=("${array3[@]}")      # reassemble array3
declare -p array3

Output:

declare -a array3=([0]="E" [1]="G")
Cyrus
  • 77,979
  • 13
  • 71
  • 125
  • Great answer. What's the point of `declare -p array3` ? – hmedia1 Jul 04 '21 at 20:20
  • @hmedia1: This only outputs array3, where you can see what is in which element. You can see the difference if you leave out `array3=("${array3[@]}")`. – Cyrus Jul 04 '21 at 20:21