【问题标题】:zsh - print array duplicates ONLYzsh - 仅打印重复的数组
【发布时间】:2020-06-09 22:55:25
【问题描述】:

不要盲目地从数组中删除重复项。

我想打印给定数组可能具有的所有重复值。

当我使用这个命令时:

printf '%s\n' "${arr[@]}" | awk '!($0 in seen){seen[$0];print $0}'

...它打印出所有唯一值,并将重复的值排除在外。

预计会适得其反,但没有得到任何结果:

printf '%s\n' "${arr[@]}" | awk '($0 in seen){seen[$0];print $0}'

示例输入:

arr=(1 2 2 3)

预期输出:

2

编辑

现在,这似乎有效。让它打开一天左右,以防有人有更好的方法......

array=($arr)
for value in ${array[@]}; do
    [[ $(grep "${value}" $(echo ${(F)arr} | wc -l) -gt 1 ]] && echo $value;
done

【问题讨论】:

  • print -l $arr|sort|uniq -d 是我通常这样做的方式。

标签: arrays duplicates zsh


【解决方案1】:

非常短:只在计数为正好 1 时打印该值(这发生在您看到的第一个重复项上):

% print -l $arr | awk 'a[$0]++ == 1'

你可以在纯zsh中做类似的事情:

% () { local -A a; for x; do ((a[$x]++ == 1)) && print $x; done } $arr
2

匿名函数只是用来本地化数组a的使用。关联数组用于容纳任何值的数组,而不仅仅是整数值。

略短,使用for的缩写形式:

% () { local -A a; for x; { ((a[$x]++ == 1)) && print $x } } $arr

【讨论】:

  • 这应该是公认的答案。我不知道那种无动作的 awk 语法 - 这比我的解决方案优雅得多!
  • 对,没有明确的行动,{ print } 被假定。
【解决方案2】:

你快到了:

printf "%s\n" "${arr[@]}" | awk '{ if (count[$0] > 0) print $0; else count[$0]++ }'

第一次看到一个值时,数组索引增加为 1。任何时候再次看到该值,该值就被打印出来。如果您只希望重复打印一次,您可以采用另一种方式:

printf "%s\n" "${arr[@]}" | awk '{ count[$0]++ } END { for (i in count) { if (count[i] > 1) print i } }'

在此版本中,每个值都用作索引,并且计数递增。最后,我们循环遍历数组并打印任何计数大于 1 的索引。您也可以使用第一个版本并简单地通过管道传递给 uniq

【讨论】:

    【解决方案3】:

    这里是纯 zsh 解决方案,无需还原到外部程序:

    arr=(1 2 2 3)
    duparr=()  # This will be the resulting array of duplicate values
    typeset -U duparr
    for s in "${arr[@]}"
    do
      if [[ ${arr[(ie)$s]} != ${arr[(Ie)$s]} ]]
      then
        duparr+=($s)
      fi
    done
    echo $duparr
    

    这里的技巧是使用数组索引修饰符标志(ie)(Ie)${arr[(ie)$s]} 返回$s$arr 中第一次出现的索引,${arr[(Ie)$s]} 返回最后一个。如果一个元素是重复的,这些索引表达式会有所不同,我们将它们收集到duparr

    但由于我们遍历整个arrduparr 现在将包含每个重复值至少两次。 typeset -U duparr 确保只存储一个事件。

    更新:将标志从(i)(即通过模式匹配查找)更改为(ie)(即按字面意思查找)。虽然差异对于问题中的具体数据无关紧要,但对于一般情况(当arr 中的字符串包含通配符时)可能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-25
      • 2014-12-08
      • 1970-01-01
      • 2015-11-17
      • 1970-01-01
      • 2019-12-11
      • 2012-05-16
      • 2020-04-23
      相关资源
      最近更新 更多