排序关联数组AWK [英] Sort associative array with AWK

查看:234
本文介绍了排序关联数组AWK的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面是我的阵列(GAWK脚本):

Here's my array (gawk script) :

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

排序后,我需要以下结果:

After sort, I need the following result :

bob    5
jack   11
peter  32
john   463

当我用ASORT,指数都将丢失。如何通过数组值不失指数排序? (我需要根据它们的值有序索引)

When i use "asort", indices are lost. How to sort by array value without losing indices ? (I need ordered indices based on their values)

(我需要获得这个结果与AWK /呆子而已,不是shell脚本,perl的,等等)

(I need to obtain this result with awk/gawk only, not shell script, perl, etc)

如果我的帖子是不够清楚,这里是一个其他后解释同一个​​问题:<一href=\"http://www.experts-exchange.com/Programming/Languages/Scripting/Shell/Q_26626841.html\">http://www.experts-exchange.com/Programming/Languages/Scripting/Shell/Q_26626841.html )

If my post isn't clear enough, here is an other post explaining the same issue : http://www.experts-exchange.com/Programming/Languages/Scripting/Shell/Q_26626841.html )

在此先感谢

更新:

感谢你们,但我需要通过值,而不是指数排序(我想根据自己的价值观指数排序)。

Thanks to you both, but i need to sort by values, not indices (i want ordered indices according to their values).

在其他方面,我需要这样的结果:

In other terms, i need this result :

bob    5
jack   11
peter  32
john   463

不是

bob 5
jack 11
john 463
peter 32

(我同意,我的例子是混乱的,所选择的值是pretty坏)

(I agree, my example is confusing, the chosen values are pretty bad)

从嘘声的code,我写了一个快速的实现这样的作品,但它是相当丑陋(我串连键和放大器;前值排序和比较期间分割)。这里是什么样子:

From the code of Catcall, I wrote a quick implementation that works, but it's rather ugly (I concatenate keys & values before sort and split during comparison). Here's what it looks like :

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

当然,我很感兴趣,如果你有更多的东西干净...

Of course I'm interested if you have something more clean...

感谢您的时间

推荐答案

编辑:

排序值

哦!到的值进行排序的,这是一个有点杂牌的,但你可以创建一个使用值的级联和原始数组作为新数组索引的索引临时数组。然后你可以 asorti()临时数组和拆分连接值回指标和值。如果你不能按照费解的描述,code是非常容易理解。它也非常短。

Oh! To sort the values, it's a bit of a kludge, but you can create a temporary array using a concatenation of the values and the indices of the original array as indices in the new array. Then you can asorti() the temporary array and split the concatenated values back into indices and values. If you can't follow that convoluted description, the code is much easier to understand. It's also very short.

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

编辑2:

如果你有GAWK 4,可以通过遍历值的顺序排列,而不执行明确的排序:

If you have GAWK 4, you can traverse the array by order of values without performing an explicit sort:

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

 }

有由指数或价值穿越,上升或下降以及其他选项的设置。您还可以指定一个自定义的功能。

There are settings for traversing by index or value, ascending or descending and other options. You can also specify a custom function.

previous答案:

分类指数

如果你有一个AWK,如 GAWK 3.1.2或更高版本,它支持 asorti()

If you have an AWK, such as gawk 3.1.2 or greater, which supports 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]]
}

如果你没有 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]]
}

这篇关于排序关联数组AWK的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆