Sort multidimensional Array

Hello

I have a problem.
I create a Multidimensional Array Like this:

        ENTRY["HOST1"]="$kunnum-$host"
        ENTRY["HOST2"]="$host"
    ENTRY["COMMENT"]="# $3"
    for key in "${!ENTRY[@]}"; do
        ENTRIES[$2"5",$key]=${ENTRY[$key]} # INDEX=IP(5)
    done
declare -p
declare -A ENTRIES=([205,HOST1]="unas15533" [205,HOST2]="unas" [1025,COMMENT]="# RDP-Terminal 2" [775,COMMENT]="# WLAN Access Point" [1015,IP]="111.122.133.101" [1025,IP]="111.122.133.102" [775,IP]="111.122.133.77" [205,COMMENT]="# UNAS" [775,HOST1]="15533-wlan" [1015,HOST2]="rdp1" [1015,HOST1]="15533-rdp1" [775,HOST2]="wlan" [1015,COMMENT]="# RDP-Terminal 1" [1025,HOST2]="rdp2" [1025,HOST1]="15533-rdp2" [205,IP]="111.122.133.20" )

Now i have to sort this by the "INDEX"

([205,HOST1]="unas15533" 

in this case it would be 205
I have to sort all elements and then i want to give them formated out.

How can I sort this array?

Thank you so much for your help.

Welcome to the forum.

Please become accustomed to provide decent context info of your problem.

It is always helpful to carefully and detailedly phrase a request, and to support it with system info like OS and shell, related environment (variables, directory structures, options), preferred tools, adequate (representative) sample input and desired output data and the logics connecting the two including your own attempts at a solution, and, if existent, system (error) messages verbatim, to avoid ambiguities and keep people from guessing.

In addition to what RudiC already said (and, by the way, if your programming language is not some shell - i assume that it is, but my assumption might be wrong - it would be nice to know which one that is). Notice, though, that most shells don't support multidimenisonal arrays and especially not assiociative arrays:

What exactly do you mean by "sort all the elements"? For a sorting you need some key - alphabetical, numerical, by date or whatever - and something to sort. An array, regardless of being multidimensional or not, contains several elements. The elements have an index - basically their position in the array - and some content. Do you want to sort the contents or the indices to be sorted?

If it is the indices: these are multi-value items in a multidimensional array and it is not clear which part of these take priority: i.e. if you have 3 entries, [1,10], [2,5] and [10,1], which one is supposed to be first? If the first element takes priority the order would be [1,10], [2,5], [10,1], if the second element takes priority you have [10,1], [2,5], [1,10], if the sum of both entries is the sort criteria it is [2,5], [1,10], [10,1], etc..

If it is the contents you are trying to sort you simply need to traverse through the indices of one dimension after the other using simple for-loops, i.e. for a 3-dimensional array with numerical indices (pseudocode):

for i in 1..10
     for j in 1..10
          for k in 1..10
               print array[i,j,k]
          next
     next
next

and sort the resulting list.

I hope this helps.

bakunin

1 Like
shuf -e ${!ENTRIES[@]} | sort -V | while read d; do echo $d=${ENTRIES[$d]}; done

--- Post updated at 12:01 ---

can play with the options of the "sort" command :slight_smile:

1 Like

Try also

echo "${!ENTRIES
[*]}" | sort -n | while read IX; do printf "%-15s%-15s\n" $IX ${ENTRIES[$IX]}; done
205,COMMENT    # UNAS         
205,HOST1      unas15533      
205,HOST2      unas           
205,IP         111.122.133.20 
775,COMMENT    # WLAN Access Point
775,HOST1      15533-wlan     
775,HOST2      wlan           
775,IP         111.122.133.77 
1015,COMMENT   # RDP-Terminal 1
1015,HOST1     15533-rdp1     
1015,HOST2     rdp1           
1015,IP        111.122.133.101
1025,COMMENT   # RDP-Terminal 2
1025,HOST1     15533-rdp2     
1025,HOST2     rdp2           
1025,IP        111.122.133.102
1 Like

Thank you for your answers

And sorry for the few informations.
I used bash

#!/bin/bash

I have to sort this nummeric.
After sorting I want to give this out in a File
In this order

# IP - HOST1  - HOST2 - COMMENT

my problem is to find an efficent way for that.
Because i dont know the index of the array entry
It could be something between 10 and 2550

ENTRIES[INDEX,$key]

I gona try your methods for sorting the array. Thanks

Does reversing a sort key help?

$ IFS=$'\n'
$ echo "${!ENTRIES
[*]}" | sort -t, -k1,1n -k2r | while read IX; do printf "%-15s%-15s\n" $IX ${ENTRIES[$IX]}; done
205,IP         111.122.133.20 
205,HOST2      unas           
205,HOST1      unas15533      
205,COMMENT    # UNAS         
775,IP         111.122.133.77 
775,HOST2      wlan           
775,HOST1      15533-wlan     
775,COMMENT    # WLAN Access Point
1015,IP        111.122.133.101
1015,HOST2     rdp1           
1015,HOST1     15533-rdp1     
1015,COMMENT   # RDP-Terminal 1
1025,IP        111.122.133.102
1025,HOST2     rdp2           
1025,HOST1     15533-rdp2     
 1025,COMMENT   # RDP-Terminal 2

Don't forget to reset your IFS afterwards.

EDIT: or, even better to get HOST1 and 2 in the right order:

echo "${!ENTRIES
[*]}" | sort -t, -k1,1n -k2,2.2r -k2.3 | while read IX; do printf "%-15s%-15s\n" $IX ${ENTRIES[$IX]}; done

Your method is not working, this is what i get back

414,IP         205,HOST1
205,HOST2      414,COMMENT
505,HOST2      505,IP
505,HOST1      1025,COMMENT
775,COMMENT    1015,IP
1025,IP        775,IP
505,COMMENT    205,COMMENT
410,IP         775,HOST1
1015,HOST2     1015,HOST1
775,HOST2      410,HOST1
1015,COMMENT   410,HOST2
414,HOST1      414,HOST2
1025,HOST2     1025,HOST1
410,COMMENT    205,IP

This methode from nezabudka even works better. this sorts my array correct

shuf -e ${!ENTRIES[@]} | sort -V | while read d; do echo $d=${ENTRIES[$d]}; done

my only problem is now how to get the this entrys in this output order

# IP - HOST1  - HOST2 - COMMENT

Did you set the IFS variable as indicated?
Try the sort keys given with netzabudka's proposal as well.

1 Like

Oh it was my fault. Its working of course as well. Thank you

So know i dont understand (my bash skills are very low) how to get this in a file line by line in this format

# IP - HOST1  - HOST2 - COMMENT

Like this

10.155.33.20              unas15533              unas      # Comment
10.155.33.101             15533-rdp1             rdp1      # Comment
10.155.33.102             15533-rdp2             rdp2      # Comment

I know how to create the file and how to write in it but i dont understand how i can use your funtion to geht this

Try paste :

echo "${!ENTRIES
[*]}" | sort -t, -k1,1n -k2,2.2r -k2.3 | while read IX; do printf "%s\n" ${ENTRIES[$IX]}; done | paste -sd"\t\t\t\n"
111.122.133.20     unas15533     unas    # UNAS
111.122.133.77     15533-wlan    wlan    # WLAN Access Point
111.122.133.101    15533-rdp1    rdp1    # RDP-Terminal 1
111.122.133.102    15533-rdp2    rdp2    # RDP-Terminal 2

Aside: How did you create those arrays? Mayhap all this messing around could be avoided, and your output correctly computed in the first place?

1 Like
shuf -e ${!ENTRIES[@]} | sort -t, -k1,1n -k2,2.2Vr |

--- Post updated at 14:02 ---

And so it works
sort -t, -k1,1n -k2,2.2r

1 Like

Thank you so much

This works perfect for me:

IFS=$'\n'
echo "${!ENTRIES[*]}" | sort -t, -k1,1n -k2,2.2r -k2.3 | while read IX; do printf "%-20s\n" ${ENTRIES[$IX]}; done | paste -sd"\t\t\t\n"