从另一个数组中删除条目数组

从另一个数组中删除条目数组

我有 2 个阵列

    a=(1,2,3,4,5)
    b=(2,4)

输出应该是

    c=(1,3,5) 

(这应该是 ab 的结果)

我试过使用

    unset a[${b}] 

有任何想法吗?

我现在正在做的是一个循环,它运行了 700,000 次迭代

答案1

首先,如果你想进行 700,000 次迭代,你真的应该研究一下 bash 以外的内容。另外,您显示的不是 bash 中的数组,而是字符串1。数组以空格分隔,而不是逗号。

也就是说,这是一个 bash 方法,假设真正的数组:

a=(1 2 3 4 5)
b=(2 4)
c=( $(printf "%s\n" "${a[@]}" "${b[@]}" | sort | uniq -u) )

如果您实际上有逗号分隔的字符串而不是数组,请改用以下命令:

a=(1,2,3,4,5)
b=(2,4)
c=( $(sed 's/,/\n/g' <(printf "%s\n" "${a[@]}" "${b[@]}") | sort | uniq -u) )

或者,你可以使用 perl 来代替:

#!/usr/bin/perl
my @A=(1,2,3,4,5);
my @B=(2,4);
my %k;
map{$k{$_}++} (@A,@B);
my @C=grep($k{$_}==1,keys(%k));
print "@C\n";

1严格来说,它是一个具有一个元素的数组,但就 bash 而言,它本质上与字符串相同。

答案2

任务的复杂性(O(N ^ 2))无法降低;仅假设明确给出的内容(即,对于数组a和的值没有假设b),下面的代码将仅检查 中存在的每个值是否a也存在于 中b,如果该值存在,它将打破内部for循环(给定假设下唯一可能的优化)并将该值添加到c;如果有关于数组a和内容的更多线索b(即,如果每个数组中的值可能重复并且数组已排序),可能还有更多的改进空间:

#!/bin/bash

a=(1 2 3 4 5)
b=(2 4)
for i in ${a[@]}
do
match=0
    for j in ${b[@]}
    do
        if [ "${i}" == "${j}" ]
        then
            match=1
            break
        fi
    done
if [ "${match}" == 0 ]
then
    c+=($i)
fi
done
echo ${c[@]}

答案3

方法perl。此脚本显示数组中的所有元素a,这些元素也包含在数组中b

#!/usr/bin/perl
my @a = (1,2,3,4,5);
my @b = (2,4,7,8,9,10);

# Create a hashmap with the entries in b as keys,
# but without values for the keys for a better lookup
# (exists ($hash{$element}))
my %hash;
@hash{@b}=();

foreach my $element (@a) {print "$element " unless exists($hash{$element})}
print "\n";

输出:

1 3 5

答案4

@terdon 接受的答案实际上并没有消除来自 的项目a也位于 中b,而是连接两个列表并删除非唯一值。当b包含 中不存在的项目时,这是一个巨大的差异ac将包含在 中b但不在 中的值a

这是一个纯 Bash 解决方案移除其中的项目a也在b(请注意附加6b):

a=(1 2 3 4 5)
b=(2 4 6)
c=( $(printf "%s\n" "${a[@]}" "${b[@]}" "${b[@]}" | sort | uniq -u) )

c将由意外情况组成1 3 5,但不包括意外情况6

如果数组项可能包含空格,请按照以下建议使用mapfile构造Array3Stack Overflow 上的 @David

a=(1 2 3 4 5)
b=(2 4 6)
mapfile -t c < <(printf "%s\n" "${a[@]}" "${b[@]}" "${b[@]}" | sort | uniq -u)

请注意:这假设 中的所有值a都是唯一的。否则它们将不会显示在 中c。如果a包含重复值,则必须先删除重复项(请注意1中的重复项a;如果您的项目包含空格,则可能使用mapfile):

a=(1 1 2 3 4 5)
b=(2 4 6)
c=( $({ printf "%s\n" "${a[@]}" | sort -u; printf "%s\n" "${b[@]}" "${b[@]}"; } | sort | uniq -u) )

如果您想将 中的重复项复制a到,请遵循@kos 的答案。如果和很大c,情况也是如此:对于很多项目来说,这是一种非常低效的解决方案,即使对于少数项目(<100)来说它可以忽略不计。如果您需要处理大型数组,请不要使用 Bash。ab

相关内容