获取bash数组中最常出现的数字

时间:2018-04-04 17:50:40

标签: bash

我需要在数组中找到最常用的数字。我是这样做的:

# our array, the most frequent value is 55
declare -a array=(44 55 55 55 66 66)

# counting unque string with uniq and then sorting as numbers
array=($(printf "%s\n" "${array[@]}"| uniq -c | sort -n -r))

# printing 2nd element of array, as the first one - number of occurencies
printf ${array[1]}

这是一种更好/更美丽的方式吗,而不是构建一个奇怪的数组(第二步),其中包含混合计数和数字?

我是否正确排序? (uniq返回2列中的值,因此我不确定它是如何选择列的)

4 个答案:

答案 0 :(得分:4)

如果我必须在bash中执行此操作,我会使用awk来跳过对任何内容的排序,并只计算元素:

printf '%s\n' "${array[@]}" | awk '{
     if (++arr[$0] > max) {
       max=arr[$0];
       ans=$0
     }
   } 
   END {print ans}'

您还可以使用关联数组在bash 4或更高版本中实现相同的算法:

# These don't strictly need to be initialized, but it's safer
# to ensure they don't already have values.
declare -A counts=()
max=0
ans=
for i in "${array[@]}"; do
  if ((++counts[$i] > max)); then
    max=${counts[$i]}
    ans=$i
  fi
done
printf '%s\n' "$ans"

答案 1 :(得分:2)

#!/usr/bin/env bash declare -a array=(44 55 55 55 66 66) declare -A hashMap declare -i max=0 for element in "${array[@]}"; do ((hashMap["$element"]++)) done for key in "${!hashMap[@]}"; do (( "${hashMap[$key]}" > max )) && { max="${hashMap[$key]}"; element="$key" ; } done printf '%d\n' "$element" v4 +向前使用关联数组的更简洁的chepner逻辑版本。我们使用key作为数组元素构建关联数组SELECT * FROM "db1"."tbl1" WHERE year = cast(extract(year from (CURRENT_DATE - interval '7' day)) as varchar) AND month = lpad(cast(extract(month from (CURRENT_DATE - interval '7' day)) as varchar),2,'0') AND day = lpad(cast(extract(day from (CURRENT_DATE - interval '7' day)) as varchar),2,'0') limit 10 ,并将其出现的计数作为值。构建数组后,我们从具有最大计数的数组中找到并检索其值。

{{1}}

答案 2 :(得分:1)

如果您不想使用 awk 执行此操作,您仍然可以使用排序 uniq 进行此操作但请注意,您需要在计数之前将输入 ALREADY 排序。否则它将无法工作。例如:

declare -a array=(34 3 45 45 66 55 44 55 55 55 66 45 45 8 6 45 45 66 32 9 18)
printf "%s\n" "${array[@]}" | sort -n -r | uniq -c | sort -n -r | head -1 | awk '{print $2}'

对于给定的输入,代码正确地提取最重复的数字,但是在你给它的样本中它将不起作用并且它将告诉55是最重复的数字,虽然这是错误的,因为它显然是45,但是 uniq 仅计算连续项目,如果它们稀疏则会错误地计算它们。

Regads!

答案 3 :(得分:1)

另一个极简主义者awk

$ awk '{for(mi=i=1;i<=NF;i++) if(a[$mi]<++a[$i]) mi=i; print $mi}' <<< "${array[@]}"