从值的字符串中获取中值

时间:2016-03-27 20:57:58

标签: linux string bash sorting median

我需要找到保存在字符串中的值的中位数。我必须在bash中实现这一点而不需要任何额外的临时文件,而我不能使用awk。

我将此字符串保存在$string

85 13 4 45 1111 89 87 66 1 5 2 51 13 66 98 50 20 14 18 16 31 21 5175 12

首先,我需要对这些值进行排序:

1 2 4 5 12 13 13 14 16 18 20 21 31 45 50 51 66 66 85 87 89 98 1111 5175

然后我需要找到这些值的中位数

(21+31) / 2 = 26

我怎样才能做到这一点? bash中是否有任何有效的方法或命令?

我的想法:

要对值进行排序,我可以使用sort,但我不确定如何强制它对字符串中的值进行排序,因为它使用了FILE。

我不知道如何达到中位数,所以我至少会欣赏小提示。

2 个答案:

答案 0 :(得分:1)

您可以使用以下命令:

@keyframes fadeOut {
      0%{
        transform: scale(1) translate3d(0,0,0);
        opacity: 1;
      }
      25% {
        transform: scale(1) translate3d(0,100px,-100px);
        opacity: 0.5;
      }
      75% {
        transform: scale(1) translate3d(-500px,100px,-100px);
        opacity: 0;
      }
      100% {
        transform: scale(1) translate3d(-500px,100px,-100px);
        opacity: 0;
        display: none;
      }
  }

  @-webkit-keyframes fadeOut {
      0%{
        -webkit-transform: scale(1) translate3d(0,0,0);
        opacity: 1;
      }
      25% {
        -webkit-transform: scale(1) translate3d(0,100px,-100px);
        opacity: 0.5;
      }
      75% {
        -webkit-transform: scale(1) translate3d(-500px,100px,-100px);
        opacity: 0;
      }
      100% {
        -webkit-transform: scale(1) translate3d(-500px,100px,-100px);
        opacity: 0;
        display: none;
      }
  }

  @keyframes fadeIn {
      0%{
        transform: scale(1) translate3d(500px,100px,-100px);
        opacity: 0;
      }
      25% {
        transform: scale(1) translate3d(500px,100px,-100px);
        opacity: 0;
      }
      75% {
        transform: scale(1) translate3d(0,100px,-100px);
        opacity: 0.5;
      }
      100% {
        transform: scale(1) translate3d(0,0,0);
        opacity: 1;
      }
  }
  @-webkit-keyframes fadeIn {
      0%{
        -webkit-transform: scale(1) translate3d(500px,100px,-100px);
        opacity: 0;
      }
      25% {
        -webkit-transform: scale(1) translate3d(500px,100px,-100px);
        opacity: 0;
      }
      75% {
        -webkit-transform: scale(1) translate3d(0,100px,-100px);
        opacity: 0.5;
      }
      100% {
        -webkit-transform: scale(1) translate3d(0,0,0);
        opacity: 1;
      }
  }
  .inactive{
    -webkit-animation: fadeOut 2s forwards;
    animation: fadeOut 2s forwards;
  }
  .active{
    -webkit-animation: fadeIn 2s forwards;
    animation: fadeIn 2s forwards;
  }

答案 1 :(得分:1)

要将字符串中的数字转换为已排序的数组,可以将它们分别打印在一个单独的行上,输入sort -n然后读入带mapfile的数组:

string='85 13 4 45 1111 89 87 66 1 5 2 51 13 66 98 50 20 14 18 16 31 21 5175 12'
mapfile -t arr < <(for num in $string; do echo "$num"; done | sort -n)

-t选项会从每个值中删除换行符。请注意,无法管道到mapfile,因为它会在子shell中,arr之后会为空。

引用变量通常是个好主意,但在这种情况下,我们依赖于单词拆分,不得引用$string

现在,对于中位数,有两种选择:

  • 有一个奇数个数组元素,我们只想要中间元素的值。
  • 存在偶数个数组元素,我们想要两个中间元素的平均值。

数组元素的数量为${#arr[@]},因此我们可以检查,然后决定要做什么:

nel=${#arr[@]}
if (( nel % 2 == 1 )); then     # Odd number of elements
    val="${arr[ $((nel/2)) ]}"
else                            # Even number of elements
    val="$(( ( arr[$((nel/2))] + arr[$((nel/2-1))] ) / 2 ))"
fi
printf "%d\n" "$val"

这依赖于整数算术:如果我们有一个奇数个元素,比如说三个,则中位数的索引是1 - 我们从3的整数除以2得到。对于偶数个元素,比如说四个,我们想要索引为1和2的元素,我们通过将较高的索引除以4得到两个索引并从中减去一个来得到较低的索引。

如果两个元素没有相加,则结果将向下舍入。如果这还不够好,我们可以检查数字是否为奇数并手动将.5添加到结果中,或者我们可以使用bc进行计算。考虑:

$ echo $(( 11/2 ))
5
$ bc <<< 'scale=1; 11/2'
5.5