Domanda

Ecco il mio array (scritto gawk):

myArray["peter"] = 32
myArray["bob"] = 5
myArray["john"] = 463
myArray["jack"] = 11

Dopo sorta, mi serve il seguente risultato:

bob    5
jack   11
peter  32
john   463

Quando uso "asort", gli indici sono persi. Come per ordinare per valore di matrice senza perdere indici? (Ho bisogno ordinato indici in base ai loro valori)

(ho bisogno di ottenere questo risultato con awk / gawk solo, non script di shell, perl, ecc)

Se il mio post non è abbastanza chiaro, qui è un altro post che spiega lo stesso problema: http://www.experts-exchange.com/Programming/Languages/Scripting/Shell/Q_26626841.html )

Grazie in anticipo

Aggiornamento:

Grazie a tutti e due, ma ho bisogno di Ordina per valori, non indici (voglio ordinato indici in base ai loro valori).

In altri termini, ho bisogno di questo risultato:

bob    5
jack   11
peter  32
john   463

non

bob 5
jack 11
john 463
peter 32

(sono d'accordo, il mio esempio è confusa, i valori scelti sono piuttosto male)

Dal codice di catcall, ho scritto una rapida attuazione che le opere, ma è piuttosto brutto (I concateno chiavi e valori prima di ordinamento e di divisione durante il confronto). Ecco come si presenta:

function qsort(A, left, right,   i, last) {
  if (left >= right)
    return
  swap(A, left, left+int((right-left+1)*rand()))
  last = left
  for (i = left+1; i <= right; i++)
    if (getPart(A[i], "value") < getPart(A[left], "value"))
      swap(A, ++last, i)
  swap(A, left, last)
  qsort(A, left, last-1)
  qsort(A, last+1, right)
}

function swap(A, i, j,   t) {
  t = A[i]; A[i] = A[j]; A[j] = t
}

function getPart(str, part) {
  if (part == "key")
    return substr(str, 1, index(str, "#")-1)
  if (part == "value")
    return substr(str, index(str, "#")+1, length(str))+0
  return
}

BEGIN {  }
      {  }
END {

  myArray["peter"] = 32
  myArray["bob"] = 5
  myArray["john"] = 463
  myArray["jack"] = 11

  for (key in myArray)
    sortvalues[j++] = key "#" myArray[key]

  qsort(sortvalues, 0, length(myArray));

  for (i = 1; i <= length(myArray); i++)
    print getPart(sortvalues[i], "key"), getPart(sortvalues[i], "value")
}

Naturalmente mi interessa se hai qualcosa di più pulito ...

Grazie per il vostro tempo

È stato utile?

Soluzione

Modifica

Ordina per valori

Oh! Per ordinare i Valori , è un po 'un ripiego, ma è possibile creare un array temporaneo utilizzando una concatenazione dei valori e gli indici della matrice originale come indici del nuovo array. Poi si può asorti() l'array temporaneo e dividere i valori concatenati di nuovo in indici e valori. Se non è possibile seguire questa descrizione contorto, il codice è molto più facile da capire. E 'anche molto breve.

# right justify the integers into space-padded strings and cat the index
# to create the new index
for (i in myArray) tmpidx[sprintf("%12s", myArray[i]),i] = i
num = asorti(tmpidx)
j = 0
for (i=1; i<=num; i++) {
    split(tmpidx[i], tmp, SUBSEP)
    indices[++j] = tmp[2]  # tmp[2] is the name
}
for (i=1; i<=num; i++) print indices[i], myArray[indices[i]]

Modifica 2:

Se avete GAWK 4, si può attraversare la matrice per ordine di valori senza eseguire una sorta esplicito:

#!/usr/bin/awk -f
BEGIN {
    myArray["peter"] = 32
    myArray["bob"] = 5
    myArray["john"] = 463
    myArray["jack"] = 11

    PROCINFO["sorted_in"] = "@val_num_asc"

    for (i in myArray) {
        {print i, myArray[i]}}
    }

 }

Ci sono le impostazioni per l'attraversamento da indice o il valore, ascendente o discendente e altre opzioni. È inoltre possibile specificare una funzione personalizzata.

Risposta precedente:

Ordina per indici

Se si dispone di un AWK, come ad esempio gawk 3.1.2 o superiore, che supporta asorti():

#!/usr/bin/awk -f
BEGIN {
    myArray["peter"] = 32
    myArray["bob"] = 5
    myArray["john"] = 463
    myArray["jack"] = 11

    num = asorti(myArray, indices)
    for (i=1; i<=num; i++) print indices[i], myArray[indices[i]]
}

Se non si dispone di asorti():

#!/usr/bin/awk -f
BEGIN {
    myArray["peter"] = 32
    myArray["bob"] = 5
    myArray["john"] = 463
    myArray["jack"] = 11

    for (i in myArray) indices[++j] = i
    num = asort(indices)
    for (i=1; i<=num; i++) print i, indices[i], myArray[indices[i]]
}

Altri suggerimenti

Il comando tipo Unix con il tubo, mantiene il codice Awk semplice e seguire Unix filosofia
Creare un file di input con i valori separati da virgola
peter, 32
Jack, 11
John, 463
bob, 5

Creare un file sort.awk con il codice

BEGIN { FS=","; }
{
    myArray[$1]=$2;
}
END {
    for (name in myArray)
        printf ("%s,%d\n", name, myArray[name]) | "sort -t, -k2 -n"
}

Eseguire il programma, dovrebbe dare l'uscita
$ Awk -f sort.awk dati
bob, 5
Jack, 11
peter, 32
John, 463

PROCINFO["sorted_in"] = "@val_num_desc";

Prima di iterare una matrice, utilizzare la dichiarazione di cui sopra. Ma, funziona in awk versione 4.0.1. Non funziona in awk versione 3.1.7.

Non sono sicuro in cui versione intermedia, ha ottenuto introdotto.

E la risposta è semplice ...

function sort_by_myArray(i1, v1, i2, v2) {
    return myArray[i2] < myArray[i1];
}

BEGIN {
    myArray["peter"] = 32;
    myArray["bob"] = 5;
    myArray["john"] = 463;
    myArray["jack"] = 11;
    len = length(myArray);

    asorti(myArray, k, "sort_by_myArray");

    # Print result.
    for(n = 1; n <= len; ++n) {
            print k[n], myArray[k[n]]
    }
}

Gli autori di L'AWK Programming Language di fornire un Quicksort funzione , che è disponibile on-line.

Credo che avresti fatto qualcosa di simile.

END {
  for (key in myArray) {
    sortkeys[j++] = key;
  }
  qsort(sortkeys, 0, length(myArray));      # Not sure I got the args right.
  for (i = 1; i <= length(myArray); i++) {
    print sortkeys[i], myArray[sortkeys[i]];
  }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top