如何以bash保留顺序获取列表的唯一值,并保持每个唯一值的最后一个值?

时间:2019-08-06 01:35:59

标签: bash

我在bash中有一个列表,其中可以包含重复的值。我想删除重复项并获取仅包含唯一值的列表。必须保留顺序,唯一值的最后一次出现是我希望保留的顺序。

例如,如果我有此列表:

A=( D B A C D )

我正在寻找:

result=( B A C D )

当数据是文件中的列表时,我已经看到了解决方案,但是我宁愿将列表保留在内存中,而不必跳过任何麻烦。

我认为我可以使用关联数组,并在列表中循环,将条目添加为数组中的键,然后将键转储到唯一列表中,但是我不是跨平台使用关联数组的专家吗?像许多C ++ STL容器一样对它们进行键值排序,或者它们保留插入顺序而不管键值如何?

尽管如此,我还是想避免依赖于关联数组,因为并非我可能需要在其上运行的所有系统都具有bash 4.x或更高版本...有些将是bash 3.x ...

任何帮助都会很棒。

1 个答案:

答案 0 :(得分:3)

没有关联数组

您可以通过使用中间索引数组来保存A中的唯一值来使用索引数组。这需要针对c[]的每个元素,例如{p>

A

使用/输出示例

#!/bin/bash

declare -a result   # declare result indexed array
declare -a c        # declare temp intermediate indexed array

A=( D B A C D )     # original with duplicates

## loop decending over A, reset found flag, loop over c, if present continue,
#  otherwise store A at index in c
for ((i = $((${#A[@]}-1)); i >= 0; i--)); do 
    found=0;
    for j in ${c[@]}; do
        [ "$j" = "${A[i]}" ] && { found=1; break; }
    done
    [ "$found" -eq '1' ] && continue
    c[i]=${A[i]}
done

## loop over c testing if index for A exists, add from c to result
for ((i = 0; i < ${#A[@]}; i++)); do 
    [ "${c[i]}" ] && result+=(${c[i]})
done

declare -p result   # output result

通过BASH_VERSION测试使用关联数组

您可以结合使用索引数组和关联数组来完成此操作,而仅通过每个数组即可。您使用关联数组$ bash lastuniqindexed.sh declare -a result='([0]="B" [1]="A" [2]="C" [3]="D")' 并以B的值作为键,并使用A作为频率数组来指示是否已看到B的元素。然后,您将A的元素存储在临时索引数组A中,以便可以将唯一值添加到c[]中,以保留原始顺序。

您可以在开始时通过bash版本测试来解决关联数组功能是否存在

result

在不使用关联数组的情况下,随着数组大小的增加,对#!/bin/bash case $BASH_VERSION in ## empty or beginning with 1, 2, 3 ''|[123].*) echo "ERROR: Bash 4.0 needed" >&2 exit 1;; esac declare -A B # declare associative array declare -a result # declare indexed array A=( D B A C D ) # original with duplicates ## loop decending over A, if B[A] doesn't exist, set B[A]=1, store in c[] for ((i = $((${#A[@]}-1)); i >= 0; i--)); do [ -n "${B[${A[i]}]}" ] || { B[${A[i]}]=1; c[i]=${A[i]};} done ## loop over c testing if index for A exists, add from c to result for ((i = 0; i < ${#A[@]}; i++)); do [ "${c[i]}" ] && result+=(${c[i]}) done declare -p result # output result 中每个条目进行原始检查的嵌套循环的效率将大大降低。

使用/输出示例

c[]

仔细检查一下,如果还有其他问题,请告诉我。