1
#!/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" )'

1
  • I've slightly modified the declare -p output, as if there's a right margin. The result can still be interpreted by bash. Commented Apr 23, 2014 at 8:42

1 Answer 1

2

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

Sign up to request clarification or add additional context in comments.

4 Comments

so I would have to loop though keys incriminating a var if key is integer?
Don't know what's meant with incriminating, but I think you've got the gist. You might want to maintain a separate list if you need to count things, though.
opps typo... incrementing like x=$x+1;... OK thanks for your help!
Clarified the alternate syntax for ordered lists after you accepted. You may want to review.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.