How to keep associative array order?

后端 未结 3 598
抹茶落季
抹茶落季 2020-12-05 02:32

I try to iterate over an associative array in Bash.

It seems to be simple, but the loop doesn\'t follow the initial order of the array.

Here is a simple scri

相关标签:
3条回答
  • 2020-12-05 03:07

    My approach is to create a sorted array of keys first:

    keys=( $( echo ${!dict[@]} | tr ' ' $'\n' | sort ) )
    for k in ${keys[@]}; do
        echo "$k=${dict[$k]}"
    done
    
    0 讨论(0)
  • 2020-12-05 03:30

    Another way to sort entries in your associative array is to keep a list of the groups as you add them as an entry in the associative array. Call this entry key "group_list". As you add each new group, append it to the group_list field, adding a blank space to separate subsequent additions. Here's one I did for an associative array I called master_array:

    master_array["group_list"]+="${new_group}";
    

    To sequence through the groups in the order you added them, sequence through the group_list field in a for loop, then you can access the group fields in the associative array. Here's a code snippet for one I wrote for master_array:

    for group in ${master_array["group_list"]}; do
        echo "${group}";
        echo "${master_array[${group},destination_directory]}";
    done
    

    and here's the output from that code:

    "linux"
    "${HOME}/Backup/home4"
    "data"
    "${HOME}/Backup/home4/data"
    "pictures"
    "${HOME}/Backup/home4/pictures"
    "pictures-archive"
    "${HOME}/Backup/home4/pictures-archive"
    "music"
    "${HOME}/Backup/home4/music"
    

    This is similar to the suggestion by Jonathan Leffler, but keeps the data with the associative array rather than needing to keep two separate disjoint arrays. As you can see, it's not in random order, nor in alphabetical order, but the order in which I added them to the array.

    Also, if you have subgroups, you can create subgroup lists for each group, and sequence through those as well. That's the reason I did it this way, to alleviate the need for multiple arrays to access the associative array, and also to allow for expansion to new subgroups without having to modify the code.

    EDIT: fixed a few typos

    0 讨论(0)
  • 2020-12-05 03:31

    As already pointed out, there is no mistake. Associative arrays are stored in a 'hash' order. If you want ordering, you don't use associative arrays. Or, you use a non-associative array as well as an associative array.

    Keep a second (non-associative) array that identifies the keys in the order that they're created. Then step through the second array, using its contents to key the first (associative) array when printing the data. Like this:

    declare -A groups;      declare -a orders;
    groups["group1"]="123"; orders+=( "group1" )
    groups["group2"]="456"; orders+=( "group2" )
    groups["group3"]="789"; orders+=( "group3" )
    groups["group4"]="abc"; orders+=( "group4" )
    groups["group5"]="def"; orders+=( "group5" )
    
    # Convoluted option 1
    for i in "${!orders[@]}"
    do
        echo "${orders[$i]}: ${groups[${orders[$i]}]}"
    done
    echo
    
    # Convoluted option 1 - 'explained'
    for i in "${!orders[@]}"
    do
        echo "$i: ${orders[$i]}: ${groups[${orders[$i]}]}"
    done
    echo
    
    # Simpler option 2 - thanks, PesaThe
    for i in "${orders[@]}"
    do
        echo "$i: ${groups[$i]}"
    done
    

    The 'simpler option 2' was suggested by PesaThe in a comment, and should be used in preference to the 'convoluted option'.

    Sample output:

    group1: 123
    group2: 456
    group3: 789
    group4: abc
    group5: def
    
    0: group1: 123
    1: group2: 456
    2: group3: 789
    3: group4: abc
    4: group5: def
    
    group1: 123
    group2: 456
    group3: 789
    group4: abc
    group5: def
    

    You probably don't want to have two statements per line like that, but it emphasizes the parallelism between the handling of the two arrays.

    The semicolons after the assignments in the question are not really necessary (though they do no active harm, beyond leaving the reader wondering 'why?').

    0 讨论(0)
提交回复
热议问题