I am using zsh
on Mac. I created a list subjects
of say 25 items in that list.
Now, I would like to run all possible pairwise comparisons between the items in the list, e.g., subject1
vs. subject2
, but without running repeated measurements (such as subject1 vs. subject2 and subject2 vs subject1) Here is my code for this task:
subjects=(Subject1 Subject2 Subject4 Subject5 Subject6 Subject7 Subject8 Subject9 Subject10 Subject11 Subject12 Subject13 Subject14 Subject15 Subject16 Subject17 Subject18 Subject19 Subject20 Subject22 Subject23 Subject24 Subject25)
for i in $subjects
do
for j in $subjects
do
if [[ $i < $j ]]
then
echo "Processing pair $i - $j ..."
fi
done
done
The problem is that zsh
skips the subjects from subject10
to subject19
and directly jumps to subject20
after comparing subject1
vs. subject9
.
Where is the flaw in my code?
CodePudding user response:
The issue is with the comparison operator used in the conditional statement if [[ $i < $j ]]
. The <
operator compares the strings lexicographically, i.e., it compares the ASCII value of the characters in the strings. In ASCII, the value of the character '1' is less than the value of the character '9', so the strings "Subject10" to "Subject19" are considered to be less than "Subject9", and the comparison between "Subject1" and "Subject10" to "Subject19" is skipped.
To fix this issue, you could use a numerical comparison operator -lt
, which compares the values of the variables as integers. First, you need to extract the numerical part of the strings by using parameter expansion, and then use the -lt
operator to compare the numerical values. Here's the modified code:
subjects=(Subject1 Subject2 Subject4 Subject5 Subject6 Subject7 Subject8 Subject9 Subject10 Subject11 Subject12 Subject13 Subject14 Subject15 Subject16 Subject17 Subject18 Subject19 Subject20 Subject22 Subject23 Subject24 Subject25)
for i in $subjects
do
for j in $subjects
do
# Extract the numerical part of the strings
i_num=${i#Subject}
j_num=${j#Subject}
# Use the -lt operator to compare the numerical values
if [[ $i_num -lt $j_num ]]
then
echo "Processing pair $i - $j ..."
fi
done
done
This should give you the expected output.