这是我的数组(gawk脚本):
myArray["peter"] = 32
myArray["bob"] = 5
myArray["john"] = 463
myArray["jack"] = 11
Run Code Online (Sandbox Code Playgroud)
排序后,我需要以下结果:
bob 5
jack 11
peter 32
john 463
Run Code Online (Sandbox Code Playgroud)
当我使用"asort"时,索引会丢失.如何按数组值排序而不丢失索引?(我需要根据它们的值排序索引)
(我需要仅使用awk/gawk获取此结果,而不是shell脚本,perl等)
如果我的帖子不够清楚,这里有另一篇文章解释同一个问题:http://www.experts-exchange.com/Programming/Languages/Scripting/Shell/Q_26626841.html)
提前致谢
更新:
多亏了你们两个,但我需要按值排序,而不是索引(我希望根据它们的值排序索引).
换句话说,我需要这个结果:
bob 5
jack 11
peter 32
john 463
Run Code Online (Sandbox Code Playgroud)
不是:
bob 5
jack 11
john 463
peter 32
Run Code Online (Sandbox Code Playgroud)
(我同意,我的例子令人困惑,选择的价值非常糟糕)
从Catcall的代码中,我编写了一个可行的快速实现,但它相当难看(我在排序和分割之前将键和值连接在一起).这是它的样子:
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")
}
Run Code Online (Sandbox Code Playgroud)
当然,如果你有更干净的东西,我很感兴趣......
谢谢你的时间
Pau*_*ce. 23
编辑:
按值排序
哦! 要对值进行排序,它有点像kludge,但您可以使用值和原始数组的索引的串联作为新数组中的索引来创建临时数组.然后你可以asorti()
使用临时数组并将连接的值拆分回索引和值.如果您无法遵循那种错综复杂的描述,则代码更容易理解.它也很短.
# 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]]
Run Code Online (Sandbox Code Playgroud)
编辑2:
如果您有GAWK 4,则可以按值的顺序遍历数组,而不执行显式排序:
#!/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]}}
}
}
Run Code Online (Sandbox Code Playgroud)
有按索引或值,升序或降序以及其他选项遍历的设置.您还可以指定自定义功能.
上一个答案:
按指数排序
如果您有AWK,例如gawk
3.1.2或更高版本,它支持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]]
}
Run Code Online (Sandbox Code Playgroud)
如果你没有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]]
}
Run Code Online (Sandbox Code Playgroud)
使用带管道的Unix排序命令,保持awk代码简单并遵循Unix哲学
创建一个输入文件,其值由逗号
peter 分隔,32
jack,11
john,463
bob,5
使用代码创建sort.awk文件
BEGIN { FS=","; }
{
myArray[$1]=$2;
}
END {
for (name in myArray)
printf ("%s,%d\n", name, myArray[name]) | "sort -t, -k2 -n"
}
Run Code Online (Sandbox Code Playgroud)
运行程序,应该给你输出
$ awk -f sort.awk数据
bob,5
jack,11
peter,32
john,463
PROCINFO["sorted_in"] = "@val_num_desc";
Run Code Online (Sandbox Code Playgroud)
在迭代数组之前,请使用上面的语句。但是,它可以在 awk 版本 4.0.1 中运行。它在 awk 版本 3.1.7 中不起作用。
我不确定它是在哪个中间版本中引入的。