Question

Voici mon tableau (script gawk):

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

Après sorte, je dois le résultat suivant:

bob    5
jack   11
peter  32
john   463

Quand je l'utilise "asort", les indices sont perdus. Comment trier par valeur de tableau sans perdre des indices? (J'ai besoin commandé des indices en fonction de leurs valeurs)

(je dois obtenir ce résultat avec awk / gawk, et non un script shell, perl, etc)

Si mon poste est pas assez clair, voici un autre poste expliquant la même question: http://www.experts-exchange.com/Programming/Languages/Scripting/Shell/Q_26626841.html )

Merci à l'avance

Mise à jour:

Merci à tous les deux, mais je dois trier par des valeurs, pas des indices (je veux commander des indices en fonction de leurs valeurs).

Dans les autres termes, j'ai besoin de ce résultat:

bob    5
jack   11
peter  32
john   463

pas:

bob 5
jack 11
john 463
peter 32

(Je suis d'accord, mon exemple est source de confusion, les valeurs choisies sont assez mauvais)

À partir du code de Catcall, je l'ai écrit une mise en œuvre rapide qui fonctionne, mais il est plutôt laid (je concaténer les clés et les valeurs avant tri et de séparation lors de la comparaison). Voici à quoi il ressemble:

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")
}

Bien sûr, je suis intéressé si vous avez quelque chose de plus propre ...

Merci pour votre temps

Était-ce utile?

La solution

Modifier

Trier par valeurs

Oh! Pour trier les valeurs , il est un peu bidouille, mais vous pouvez créer un tableau temporaire en utilisant une concaténation des valeurs et les indices du tableau d'origine sous forme d'indices dans le nouveau tableau. Ensuite, vous pouvez asorti() le tableau temporaire et diviser les valeurs concaténées de nouveau dans les indices et les valeurs. Si vous ne pouvez pas suivre cette description alambiquée, le code est beaucoup plus facile à comprendre. Il est également très court.

# 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]]

Edit 2:

Si vous avez GAWK 4, vous pouvez parcourir le tableau par ordre de valeurs sans effectuer une sorte explicite:

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

 }

Il existe des paramètres pour parcourir par index ou valeur, par ordre croissant ou décroissant et d'autres options. Vous pouvez également spécifier une fonction personnalisée.

Réponse précédente:

Trier par indices

Si vous avez un AWK, comme gawk 3.1.2 ou plus, qui prend en charge 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]]
}

Si vous n'avez pas 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]]
}

Autres conseils

Utilisez la commande de tri Unix avec le tuyau, garde code simple et awk suivre la philosophie Unix
Créez un fichier d'entrée avec des valeurs séparées par des virgules
Peter, 32
Jack, 11
john, 463
plomb, 5

Créez un fichier sort.awk avec le code

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

Exécutez le programme, devrait vous donner la sortie
$ Data awk -f sort.awk
bob, 5
Jack, 11
Peter, 32
john, 463

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

Avant itérer un tableau, utilisez l'instruction ci-dessus. Mais, cela fonctionne dans la version 4.0.1 awk. Il ne fonctionne pas dans la version 3.1.7 awk.

Je ne suis pas sûr dans la version intermédiaire, il a obtenu introduit.

Et la réponse simple ...

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]]
    }
}

Les auteurs de Le Awk Langage de programmation fournir une fonction quicksort, qui est disponible en ligne.

Je pense que vous feriez quelque chose comme ça.

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]];
  }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top