如何删除数组中的所有匹配项,并将剩余部分左移?

时间:2019-02-11 08:40:29

标签: c#

我们有两个整数数组a1a2作为参数,我们应该从a2中删除所有出现的a1值。通过将所有后续元素向左移动一个索引以覆盖它,将“后续”元素“删除”,最后一个索引为0。 a1元素的原始相对顺序应保留。

我在移动元素时遇到问题。

示例:

int[] a1 = { 42, 3, 9, 42, 42, 0, 42, 9, 42, 42, 17, 8, 2222, 4, 9, 0, 1};

int[] a2 = { 42, 2222, 9};

最终结果应该是这样的:

{3, 0, 17, 8, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

这是我的代码:

for(int i = 0; i < a1.Length; i++)
{
    foreach(var element in a2)
    {
        if (element == a1[i])
        {
            for(int j = i; j < a1.Length-1; j++)
            {
                a1[j] = a1[j+1];
            }
            a1[a1.Length - 1] = 0;
        }
    }
}

5 个答案:

答案 0 :(得分:3)

项目匹配时,您需要使用i--;。因为您要转移整个阵列。另外,您还需要在break;之后使用foreach内部i--;循环。

说明

1)对于您的数组,i = 0foreach(var element in a2)中的第一个元素都将是42。因此,首先您的数组将移动一个索引。现在,如果您不使用i--,它将检查应为i=1的{​​{1}},但是由于我们已经移动了数组,因此3的值位于索引{{1} }。因此,永远不会检查此值是否匹配。

2)并使用3,因为已经找到了匹配项并且数组已移动,所以无需进一步检查。

您的代码应如下所示。

0

如果可以使用Linq,请尝试以下操作:首先获取过滤器元素。然后为其余索引添加break

for(int i = 0; i < a1.Length; i++)
{       
    foreach(var element in a2)
    {
        if (element == a1[i])
        {
            for(int j = i; j < a1.Length-1; j++)
            {
                a1[j] = a1[j+1];
            }
            a1[a1.Length - 1] = 0;
            i--;
            break;
        }
    }
}

答案 1 :(得分:1)

您可以这样做而无需创建任何额外的数组,像这样:

static void Main()
{
    int[] a1 = { 42, 3, 9, 42, 42, 0, 42, 9, 42, 42, 17, 8, 2222, 4, 9, 0, 1 };
    int[] a2 = { 42, 2222, 9 };

    int j = 0;

    for (int i = 0; i < a1.Length; ++i)
        if (Array.IndexOf(a2, a1[i]) < 0) // Don't remove this value.
            a1[j++] = a1[i];

    Array.Clear(a1, j, a1.Length-j);

    Console.WriteLine(string.Join(", ", a1));
}

我们进行了两次遍历:首先(通过显式循环)删除a1中包含的a2的所有元素,然后用{{1}覆盖所有“已删除”的值}(通过0

答案 2 :(得分:0)

另一种方法是先过滤然后添加所需的零:

int[] a1 = { 42, 3, 9, 42, 42, 0, 42, 9, 42, 42, 17, 8, 2222, 4, 9, 0, 1 };
int[] a2 = { 42, 2222, 9 };

var zeros = Enumerable.Repeat(0, int.MaxValue);
var valids = a1.Where(v => !a2.Contains(v));
var result = valids.Concat(zeros).Take(a1.Length);

Console.WriteLine(String.Join(", ", result));

答案 3 :(得分:0)

另一种方法,使用Array.Copy进行移位:

public static void Main()
{               
    int[] a1 = { 42, 3, 9, 42, 42, 0, 42, 9, 42, 42, 17, 8, 2222, 4, 9, 0, 1 };
    int[] a2 = { 42, 2222, 9 };

    for(int i = 0; i < a1.Length; i++)
    {
        if(a2.Contains(a1[i]))
        {
            //notice i-- here because iterating array shifted to left
            ShiftToLeft(a1, i--+1);         
        }
    }

    Console.WriteLine(string.Join(",", a1));
}

private static void ShiftToLeft(int[] array, int fromIndex)
{
    Array.Copy(array, fromIndex, array, fromIndex-1, array.Length - fromIndex);
    array[array.Length-1] = 0;
}

答案 4 :(得分:0)

尝试一下:

            int[] a1 = { 42, 3, 9, 42, 42, 0, 42, 9, 42, 42, 17, 8, 2222, 4, 9, 0, 1 };
            int[] a2 = { 42, 2222, 9 };

            var result = a1.Where(x => !a2.Contains(x)).Concat(new int[a1.Length]).Take(a1.Length);

            Console.WriteLine(String.Join(", ", result));