snowkiterdude
snowkiterdude

Reputation: 15

Bash get the number if integer indexed elements in array

#!/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

Answers (1)

Henk Langeveld
Henk Langeveld

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

Related Questions