Reputation: 15
#!/bin/bash
Lets say you have an array with both integer indexes and string indexes like so...
Edit... Note: This block will be in a loop in my app
declare -A arr
arr[${#arr[@]}]=someVal1
arr[${#arr[@]}]=someVal2
arr[someBool]=true
arr[someOtherString]="Some Text"
arr[${#arr[@]}]=someVal3
Now lets say I want to compare the number of array items for some reason...
[ "${#arr[@]}" = 5 ] && echo "there are 5 array items";
output...
there are 5 array items
Ok thats all and good but lets take a look at our array
declare -p arr
exit
output...
declare -A arr='([someBool]="true" [someOtherString]="Some Text"
[0]="someVal1" [1]="someVal2" [4]="someVal3" )'
Notice that the integer indexes go 0,1,4
So my Question is what should replace
arr[${#arr[@]}]=
so that the integer array indexes work out properly? (0,1,2)
Edit... Temp Solution Based on Henk Langeveld's input... Temp because it should be able to edit an array passed to it not just edit a global array statically.
#!/bin/bash
getArrIntIndexNum(){
local x=0
for i in "${!arr[@]}"; do
[[ $i =~ ^-?[0-9]+$ ]] && x=$((x+1))
done
echo $x
}
declare -A arr
arr[$(getArrIntIndexNum)]=someVal1
arr[$(getArrIntIndexNum)]=someVal2
arr[someBool]=true
arr[someOtherString]="Some Text"
arr[$(getArrIntIndexNum)]=someVal3
declare -p arr
output...
declare -A arr='([someBool]="true" [someOtherString]="Some Text" [0]="someVal1" [1]="someVal2" [2]="someVal3" )'
Upvotes: 1
Views: 446
Reputation: 8446
I'm adding a warning here: You should really split this structure, because what you're trying to do (are told to do) is mixing two different data types.
Bash and ksh93 support both ordered arrays (with an integer index) and unordered associative arrays (mappings keyed with string values).
So, the thing called:
an array with both integer indexes and string indexes
is actually an associative array, with strings for keys.
When updating a map, you can only add or remove elements by key.
Associative arrays are optimised to find any random key, while arrays are optimised for access by offset, and looping through an index. Emulating one with the other will incur greater complexity, will be harder to maintain, and will degrade performance.
When all you need is an ordered list in either ksh or bash, use
typeset -a list=( value1 value2 )
In bash, you can substitute declare
for typeset
. In older versions of ksh
you
may need to use set -A list value1 value2
Upvotes: 2