Reputation: 337
I came over this cool Bash function for checking if an array contains an element:
CONTAINS_ELEMENT(){
local e
for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done
return 1
}
Here is an example of it's usage:
if CONTAINS_ELEMENT $element "${array[@]}"; then
...
fi
My question is this: Is there a way to rewrite this function so that it can check if any value within an array is equal to any value withing the other array, and not just check for one single value as it corrently does?
Upvotes: 6
Views: 5107
Reputation: 203
Loop inside loop:
#!/bin/bash
clear
arrA=("a" "b" "c" "d" "e" "f")
arrZERO=("c" "e") # must be turned to "0"
echo "arrA:"
echo ${arrA[@]}
echo ""
echo "arrZERO:"
echo ${arrZERO[@]}
for (( i=0; i < ${#arrA[@]}; i++ ))
do
for (( j=0; j < ${#arrZERO[@]}; j++ ))
do
if [[ ${arrA[$i]} = ${arrZERO[$j]} ]]; then
arrA[$i]="0"
fi
done
done
echo ""
echo "FINAL"
echo ${arrA[@]}
Terminal will show:
arrA:
a b c d e f
arrZERO:
c e
FINAL
a b 0 d 0 f
Upvotes: 1
Reputation: 337
Looking at the links above I came over a solution that almost does what I need it to do, but not quite:
parameters=($1 $2 $3 $4)
arg1=(h help -h --help)
PARAMETERS(){
pr1=" $parameters[@]} "
for item in ${@:1}; do
if [[ $pr1 =~ " $item " ]]; then
return 0
else
return 1
fi
done
}
if PARAMETERS "${arg1[@]}"; then
echo "It works!"
else
echo "Nope, still not working..."
fi
Now this code works when passing the parameter "h", but not when passing the other parameters in the array (-h --help help). Sorry if I am doing some stupid mistake here, I am somewhat of a nuub when it comes to bash scripting :)
Upvotes: 0
Reputation: 7610
CORRECTED#3
Try code bellow. ArrContains
take two arguments, the name of the two arrays. It creates a temporary hash from lArr1
and then check if any elements of lArr2
is in the hash. This way the embedded for
-loops can be avoided.
#!/usr/bin/bash
ArrContains(){
local lArr1 lArr2
declare -A tmp
eval lArr1=("\"\${$1[@]}\"")
eval lArr2=("\"\${$2[@]}\"")
for i in "${lArr1[@]}";{ ((++tmp['$i']));}
for i in "${lArr2[@]}";{ [ -n "${tmp[$i]}" ] && return 0;}
return 1
}
arr1=("a b" b c)
arr2=(x 'b c' e)
arr3=(q a\ b y)
ArrContains arr1 arr2 && echo Contains arr1 arr2
ArrContains arr1 arr3 && echo Contains arr1 arr3
Output:
Contains arr1 arr3
Other way could be to define some separation character and concatenate the first hash. Then search for matching the SEPitemSEP
string.
ArrContainsRe(){
local lArr1 lArr2 tmp
eval lArr1=("\"\${$1[@]}\"")
printf -v tmp ",%s" "${lArr1[@]}";
tmp="$tmp,"
eval lArr2=("\"\${$2[@]}\"")
for i in "${lArr2[@]}";{ [[ $tmp =~ ,$i, ]] && return 0;}
return 1
}
...
ArrContainsRe arr1 arr2 && echo ContainsRe arr1 arr2
ArrContainsRe arr1 arr3 && echo ContainsRe arr1 arr3
Output:
ContainsRe arr1 arr3
Upvotes: 3
Reputation: 58788
This should do it:
any_overlap() {
for e1 in "${array1[@]}"
do
for e2 in "${array2[@]}"
do
if [[ "$e1" = "$e2" ]]
then
return 0
fi
done
done
return 1
}
Test session:
$ array1=(foo bar baz) array2=(ban bat bar) && any_overlap; echo $?
0
$ array1=(foo bar baz) array2=(ban bat) && any_overlap; echo $?
1
$ array1=() array2=() && any_overlap; echo $?
1
Of course, there are faster ways to do it if the arrays are sorted or none of the array elements contain whitespace.
Upvotes: -1