I have a sparse array in bash where I don't know the value of the lowest numbered index, and I want to pull that value out with its index. How do I find it?
#/bin/bash
a=( [12]="blue" [31]="violet" [59]="paisley" )
index=?
I want the first one.
I have a sparse array in bash where I don't know the value of the lowest numbered index, and I want to pull that value out with its index. How do I find it?
#/bin/bash
a=( [12]="blue" [31]="violet" [59]="paisley" )
index=?
I want the first one.
Transfer the numerical indices to an array and use its first element:
a=( [59]="paisley" [12]="blue" [31]="violet" )
arr=("${!a[@]}"); echo "${a[${arr[0]}]}"
Output:
blue
Easy. Break a for
loop.
#/bin/bash
a=( [12]="blue" [31]="violet" [59]="paisley" )
for index in "${!a[@]}"; do break; done
value="${a[$index]}"
echo "$index - $value"
Another way using read
:
a=( [12]="blue" [31]="violet" [59]="paisley" )
read -a ind <<< "${!a[@]}"
echo "$ind" # will give 12
echo "${ind[0]}" # will also give 12
echo "${a[ind]}" # blue
Given this ordinary array:
a=( [12]="blue" [31]="violet" [59]="paisley" )
You can get a return of the integer indices like so:
$ printf "%s\n" "${!a[@]}"
12
31
59
They will be ordered -- if an ordinary indexed array regardless if sparse or not.
Then you can use those indices as you wish.
If you just want the "lowest numbered index" as in the first one that pops out of that array as Bash has sorted them:
$ printf "%s\n" "${!a[@]}" | head -1
12
BEWARE, however, that Bash associative arrays are unordered and this will not produce the same results.
For an associative array with integer indices, you can sort numerically to get 12 because 12<31<59
:
$ printf "%s\n" "${!a[@]}" | sort -n | head -1
12
Then use that as the index back to the original array:
idx=$(printf "%s\n" "${!a[@]}" | sort -n | tail -1) # largest now...
echo "${a[idx]}" # paisley
With regular arrays sparse or not, you can use the same method without sort
.
The following assumes your array is an indexed array, not an associative array, that is, was not declared with declare -A a
.
According the source code of GNU bash 5.2 (current stable version), indexed arrays are implemented as sparse doubly-linked lists, the elements are inserted / deleted in numeric order, and ${!a[@]}
expands as the sorted list of indexes (numeric order). This is not documented anywhere, so relying on it is a bit dangerous, but if your bash is GNU bash 5.2 (or another version that implements indexed arrays the same way) you can simply try:
index=( ${!a[@]} )
printf 'a[%d] = %s\n' "$index" "${a[index]}"
If you do not know for sure what the order of ${!a[@]}
is, or if safety is essential (do not forget that future bash versions could make different choices, e.g. for performance reasons), you can use a for loop to find the minimum index value:
index=( ${!a[@]} )
for n in "${!a[@]}"; do (( index = n < index ? n : index )); done
printf 'a[%d] = %s\n' "$index" "${a[index]}"
"blue"
because it is the first element in the construction ofa
or because12<31<59
? – dawg Commented Jan 7 at 1:36sort
to sort them. Make up your mind whether you need them sorted numerically or alphabetically. – user1934428 Commented Jan 7 at 12:23