Associative arrays (Bash): verschil tussen versies
Regel 74: | Regel 74: | ||
Additionally, the syntax with <code>#</code> for reading out the length of an array, illustrates that arrays are basically one-dimensional. | Additionally, the syntax with <code>#</code> for reading out the length of an array, illustrates that arrays are basically one-dimensional. | ||
− | + | == Solutions == | |
* Always have arrays start with the same number ⇒ I prefer ''base 1'', just as in matrix algebra | * Always have arrays start with the same number ⇒ I prefer ''base 1'', just as in matrix algebra | ||
− | * First dimensions is ''rows'' (x) and the second is ''columns'' (y) - Just as in matrix algebra | + | * First dimensions is always ''rows'' (x) and the second is ''columns'' (y) - Just as in matrix algebra |
− | * Store the dimensions in associated variables. E.g., in the example above: <code>j_rows=3</code> and <code>j_columns=2</code> | + | * Don't use spaces around the <code>,</code> that separates indices: It messes up language highlighting in Sublime Text |
+ | * Store the dimensions in associated variables (when needed). E.g., in the example above: <code>j_rows=3</code> and <code>j_columns=2</code> | ||
== Examples == | == Examples == |
Versie van 28 sep 2022 21:12
- Associative arrays are arrays where you can give elements their own name
- You can use associative arrays to mimic multi-dimensional arrays, with emphasize on mimic
- Associative arrays are new in Bash 4. To verify which version of Bash you have:
bash --version
An associative array means, that the index doesn't have to be a number, but can be symbolic, or a key. E.g.:
declare -A j j[fruit]=apple j[color]=blue
Emulating multidimensional arrays
Associative arrays aren't really multidimensional arrays, they only emulate them. As an example:
unset j declare -A j j[0,0]="00" j[0,1]="01" j[0, 1]="0 1" for i in "${!j[@]}" do echo "Index: $i - Value: ${j[$i]}" done
Output:
Index: 0, 1 - Value: 0 1 Index: 0,1 - Value: 01 Index: 0,0 - Value: 00
So, the entry with index [0, 1]
, is not the same as with index [0,1]
. This shows that the whole index is used as one index. Not as something multidimensional.
But does this actually matter? You can include variables for these indices, and I don't really need to make calculations concerning different dimensions.
Number of rows or columns?
A problem with this 'emulated' multi-dimensional arrays: You can't read-out the number of rows or columns, for there are no real rows and columns. Illustration:
# The array below is 3x2 # unset j declare -A j j[1,1]="11" j[1,2]="12" j[2,1]="21" j[2,2]="22" j[3,1]="31" j[3,2]="32" echo "Length: ${#j[@]}" echo "Complete array: ${j[@]}"
Output:
Length: 6 Complete array: 21 22 31 31 12 11
This can be a problem, when you want to loop over the rows - Can't do that.
Additionally, the syntax with #
for reading out the length of an array, illustrates that arrays are basically one-dimensional.
Solutions
- Always have arrays start with the same number ⇒ I prefer base 1, just as in matrix algebra
- First dimensions is always rows (x) and the second is columns (y) - Just as in matrix algebra
- Don't use spaces around the
,
that separates indices: It messes up language highlighting in Sublime Text - Store the dimensions in associated variables (when needed). E.g., in the example above:
j_rows=3
andj_columns=2
Examples
As stated above, these are not really multidimensional arrays, just arrays with fancy indices. It doesn't matter if these indices are numerical or symbolic:
declare -A j j[0,0,0]="000" j[0,0,1]="001" j[0,1,0]="010" j[0,1,1]="011" j[1,0,0]="100" j[1,0,1]="101" j[1,1,0]="110" j[1,1,1]="111" echo "${j[0,0,0]} ${j[0,0,1]} ${j[0,1,0]} ${j[0,1,1]}" echo "${j[1,0,0]} ${j[1,0,1]} ${j[1,1,0]} ${j[1,1,1]}"
unset j declare -A j j[fruit,one]=Mango j[fruit,two]=Apple j[bird,1]=Cockatail j[bird,2]=Spottingbird j[flower,1]=Rose j[flower,2]=Sunflower j[animal]=Tiger for i in "${j[@]}" do echo "Entry: $i" done
Output:
Entry: Cockatail Entry: Spottingbird Entry: Rose Entry: Sunflower Entry: Tiger Entry: Apple Entry: Mango
Note that the entries seem to appear in arbitrary order
Loop through an array
Again: These are not multidimensional arrays. They only seem that way.....
This works [1]:
declare -A j j[fruit]=Mango j[bird]=Cockatail j[flower]=Rose j[animal]=Tiger for i in "${j[@]}" do echo "Entry: $i" done
Output:
Entry: Mango Entry: Rose Entry: Tiger Entry: Cockatail
This works:
declare -A j j[fruit,1]=Mango j[fruit,2]=Apple j[bird,1]=Cockatail j[bird,2]=Spottingbird j[flower,1]=Rose j[flower,2]=Sunflower j[animal,1]=Tiger j[animal,1]=Mouse for i in "${j[@]}" do echo "Entry: $i" done
Output:
Entry: Cockatail Entry: Spottingbird Entry: Rose Entry: Sunflower Entry: Mouse Entry: Mango Entry: Apple
The only problem: The entries seem to be quite random. This is also the case if I insert statement unset assArray1
at the beginning of the script.
Looping through the rows of an associate array: This one isn't as cool as the code before, because the index is given explicitly:
i=1 for ((i; i<=$number_of_sites; i++)) do echo "Row ${i}: ${site[$i,1]} & ${site[$i,2]}" done
Loop through the index of an array
This works:
declare -A j j[fruit,1]=Mango j[fruit,2]=Apple j[bird,1]=Cockatail j[bird,2]=Spottingbird j[flower,1]=Rose j[flower,2]=Sunflower j[animal,1]=Tiger j[animal,1]=Mouse for i in "${!j[@]}" do echo "Index: $i" done
With output:
Index: bird,1 Index: bird,2 Index: flower,1 Index: flower,2 Index: animal,1 Index: fruit,1 Index: fruit,2
However, this is totally not exciting: The index was explicitly specified when initialising the array. That's different when you initialise an array through e.g., i= ( 1 2 3 blub 5 )
(or whatever the exact syntax is).
Index + value
Again, not very exciting, but maybe instructive at times:
unset j declare -A j j[fruit,one]=Mango j[fruit,two]=Apple j[bird,1]=Cockatail j[bird,2]=Spottingbird j[flower,1]=Rose j[flower,2]=Sunflower j[animal]=Tiger for i in "${!j[@]}" do echo "Index: $i - Value: ${j[$i]}" done
Output:
Index: bird,1 - Value: Cockatail Index: bird,2 - Value: Spottingbird Index: flower,1 - Value: Rose Index: flower,2 - Value: Sunflower Index: animal - Value: Tiger Index: fruit,two - Value: Apple Index: fruit,one - Value: Mango
Awk
And for something entirely else: I kinda moved from a spreadsheet to associative arrays. A while ago I saw on YouTube Gary Explains: EVERYONE Needs to Learn a Little Bit of AWK! - Maybe this is what I need?