【问题标题】:Bash sorting the values of Map in descending orderBash 按降序对 Map 的值进行排序
【发布时间】:2022-01-06 04:48:19
【问题描述】:

我已经在 bash 中声明了一个地图,如下所示

declare -A myMap
myMap=( [A:B:C:D]=813.0 [P:Q:R:S]=2346957.02 [W:X:Y:Z]=53831.93 [E:F:G:H]=113770.0)

我想在具有分隔符 (:) 的 Key 中拆分字符串,并像这样按值的降序获取输出

P - Q - R - S - 2346957.02    
E - F - G - H - 113770.0    
W - X - Y - Z - 53831.93    
A - B - C - D - 813.0

我正在尝试的代码如下

for k in "${!myMap[@]}"    
do    
  arrIN=(${k//:/ })    
  echo ${arrIN[0]} ' - ' ${arrIN[1]} ' - ' ${arrIN[2]} ' - ' ${arrIN[3]} ' - ' ${myMap["$k"]}    
done | sort ${myMap["$k"]}

但是使用我的代码的输出是这样的

E - F - G - H - 113770.0    
W - X - Y - Z - 53831.93    
P - Q - R - S - 2346957.02    
A - B - C - D - 813.0

有没有简单的方法来实现这一点?

【问题讨论】:

    标签: bash sorting dictionary key-value


    【解决方案1】:

    如果您打印原始键和值,请按第二列 (k2)、numeric reverse 排序。

    #! /bin/bash
    declare -A myMap
    myMap=( [A:B:C:D]=813.0 [P:Q:R:S]=2346957.02 [W:X:Y:Z]=53831.93 [E:F:G:H]=113770.0)
    
    for k in ${!myMap[@]} ; do
        echo $k ${myMap[$k]}
    done | sort -rnk2 | sed 's/[: ]/ - /g'
    

    如果拆分key,需要按第九列排序:

    for k in "${!myMap[@]}" ; do    
        arrIN=(${k//:/ })
        echo ${arrIN[0]} - ${arrIN[1]} - ${arrIN[2]} - ${arrIN[3]} - ${myMap[$k]}
    done | sort -nrk9
    

    【讨论】:

    • 感谢这项工作。但是你如何确定这一点?如果我有 4 个文本要拆分键,那么我需要使用第 9 列。有没有与此相关的文档?
    • 4 列为键,4 列为破折号,4+4=8,值为第 9。基本上,它是数学:键数乘以 2 + 1。
    【解决方案2】:

    使用文件名通配符对键进行排序的替代方法。

    #!/usr/bin/env bash
    
    declare -A myMap
    myMap=( [A:B:C:D]=813.0 [P:Q:R:S]=2346957.02 [W:X:Y:Z]=53831.93 [E:F:G:H]=113770.0)
    
    tmpDir=
    trap 'rm -fr "$tmpDir"' EXIT INT
    tmpDir=$(mktemp -d)
    
    myKeys=("${!myMap[@]}")
    
    # Create a file per key in the temp directory
    touch "${myKeys[@]/#/$tmpDir/}"
    
    # Load keys from temp directory benefiting from auto sorting
    myKeys=("$tmpDir/"*)
    
    # Strip file path from keys
    myKeys=("${myKeys[@]##*/}")
    
    # Iterate keys in reverse order
    for (( i=${#myKeys[@]}-1; i>=0; i-- )); do
    
      k=${myKeys[i]}
    
      # Split key by :
      IFS=: read -ra ka <<<"$k"
    
      # Get corresponding value
      v=${myMap[$k]}
    
      # Print joined key elements with " - " followed by value
      printf '%s%s%s%s%s\n' "${ka[@]/%/ - }" "$v"
    done
    

    【讨论】:

      猜你喜欢
      • 2021-08-09
      • 2021-10-12
      • 2014-10-29
      • 2012-07-23
      • 2016-03-10
      • 2023-04-07
      • 1970-01-01
      • 2020-03-19
      • 1970-01-01
      相关资源
      最近更新 更多