在bash中查找数组的最高N值

时间:2018-05-29 07:35:03

标签: bash shell

我试图在数组中找到前N个值。到目前为止,我能够找到最高的一个,但不能迭代并找到其他N-1值:

ar=(10 30 44 44 69 12 11)
max=${ar[0]}
for n in "${ar[@]}" ; do
    ((n > max)) && max=$n
done
echo $max

我想我无法对数组进行排序,因为我需要打印n个较高的值(例如4)和相应的索引(数组中的原始位置)。

我的数组输出示例" ar":

值:69,指数:4

值:44,指数:3

值:44,指数:2

值:30,指数:1

2 个答案:

答案 0 :(得分:1)

如果你有阵列,

ar=(10 30 44 44 69 12 11)

并且您想要前3个最大值,然后您需要反向排序数组并选择前3个值。

但是,您无法对${ar[@]}的结果进行排序,因为这会将所有值列在一行中,sort会对行进行排序。因此,您使用printf技巧将您的值行转换为每行一个值,例如

printf "%s\n" ${ar[@]} 

注意: ${ar[@]} 故意未加引号)

然后要排序并选择顶部3,您可以这样做:

$ printf "%s\n" ${ar[@]} | sort -rn | head -3)
69
44
44

如果您只想要非常值,请将已排序的结果导出到uniq,或者如果您的sort支持-u(唯一)选项,只需添加-u),例如

$ printf "%s\n" ${ar[@]} | sort -rnu | head -3)
69
44
30

如果要捕获新数组中的前3个,只需将命令放在命令替换中,例如

$ newar=( $(printf "%s\n" ${ar[@]} | sort -rnu | head -3) )

将原始索引映射到排序

在您的注释的后续内容中,将原始索引映射到前n个排序值的最简单方法是使用索引输出原始数组,然后使用-k KEYDEF对值字段进行排序(字段2)然后输出原始索引以及排序值:

#!/bin/bash

ar=(10 30 44 44 69 12 11)

{
for ((i = 0; i < ${#ar[@]}; i++)); do
    printf "%d %d\n" "$i" "${ar[i]}"
done
} | sort -rn -k2 | head -n 3

示例使用/输出

$ bash asort2.sh
4 69
3 44
2 44

或添加-u以删除重复项:

$ bash asort2.sh
4 69
2 44
1 30

仔细看看,如果您有疑问,请告诉我。

答案 1 :(得分:0)

我在剧本中使用了这个:

IFS=$'\n' sorted_ar=($(sort -r <<<"${ar[*]}"))  # sort ar

n=4                                             # top count
for (( i=0 ; i<n ; i++ ))
do 
  echo "${sorted_ar[i]}"
done

unset IFS