从2d数组中删除重复值

时间:2017-05-03 11:39:40

标签: c# arrays

我有这样的二维数组。

int[,] arr = new int[3,5]{
             {1,2,3,4,5},
             {10,22,53,4,35},
             {1,12,13,45,51}};

现在我想删除保持顺序完整的所有重复值(即删除其他元素的值索引后不应更改)

预期输出为:

1  2  3  4  5
10 22 53 0  0
0  12 13 45 51 

注意:重复值可以替换为0。

这是我的尝试。谁能告诉我我做错了什么。

 for (int i = 0; i < 3; i++)
        {
            for (int j = 0; j < 5; j++)
            {
                int a = matrix[i, j];
                int flag = 1;
                for (int k = 0; k < 3; k++)
                {
                    for (int l = 0; l < 5; l++)
                    {
                        if (a == matrix[k, l] && flag == 0)
                        {
                            matrix[k, l] = 0;
                        }
                        else if (a == matrix[k, l] && flag != 0)
                        {
                            flag--;
                        }
                    }
                }
            }
        }

P.S。有没有其他方法可以做到这一点,没有迭代4 for循环?

4 个答案:

答案 0 :(得分:4)

我建议使用HashSet来跟踪您已经看过的数字

var seen = new HasSet<int>();
for (int i = 0; i < matrix.GetLength(0); i++)
{
    for (int j = 0; j < matrix.GetLength(1); j++)
    {
        if(!seen.Add(matrix[i,j]))
        {
            matrix[i,j] = 0;
        }
    }
}

这是有效的,因为如果值已经在哈希集中,HashSet<T>.Add将返回false

另请注意使用GetLength而不是硬编码长度。这将使代码更具可重用性,因为您不需要更改它以使其适用于不同大小的数组。

答案 1 :(得分:3)

以下是如何在更加开发人员友好模式中实现此功能的示例:

static void Main(string[] args)
{
    int[,] arr = new int[3, 5]{
     {1,2,3,4,5},
     {10,22,53,4,35},
     {1,12,13,45,51}};

    int[,] newArray = new int[arr.GetLength(0), arr.GetLength(1)];
    for (int i = 0; i < arr.GetLength(0); i++)
    {
        for (int j = 0; j < arr.GetLength(1); j++)
        {
            if (!ArrayHasValue(newArray, arr[i, j]))
            {
                newArray[i, j] = arr[i, j];
            }
            else
            {
                newArray[i, j] = 0;
            }
        }
    }
    for (int i = 0; i < newArray.GetLength(0); i++)
    {
        for (int j = 0; j < newArray.GetLength(1); j++)
        {
            Console.Write(newArray[i, j]+" ");
        }
        Console.WriteLine();
    }
}

public static bool ArrayHasValue<T>(T [,] arr, T value)
{
    for (int i = 0; i < arr.GetLength(0); i++)
    {
        for (int j = 0; j < arr.GetLength(1); j++)
        {
            if (arr[i,j].Equals(value))
                return true;
        }
    }
    return false;
}

当然,如果你不使用int数组,那么ArrayHasValue的实现并不是最好的,需要更多的验证。

答案 2 :(得分:1)

我的尝试:

int[,] arr = new int[3, 5]{
             {1,2,3,4,5},
             {10,22,53,4,35},
             {1,12,13,45,51}};

var rowsize = arr.GetLength(1);
var colsize = arr.GetLength(0);
var size = rowsize * colsize;

// index = row*rowlength + col
for (int idx1 = 0; idx1 < size; idx1++)
{
    var col = idx1 % rowsize;
    var row = idx1 / rowsize;
    var value = arr[row, col];
    if (value == 0) continue; // ignore 0's

    for (int idx2 = idx1 + 1; idx2 < size; idx2++)
    {
        var col2 = idx2 % rowsize;
        var row2 = idx2 / rowsize;
        if (arr[row2, col2] == value)
        {
            arr[row2, col2] = 0;
        }
    }
}
  • 将二维数组视为一维数组。这节省了两个循环
  • 遍历整个数组,注意那里的值
  • 遍历数组的其余(跳过您已经拥有的部分),检查所提到的值并找到设置为0
  • 使用GetLength来避免硬编码数组的大小。

答案 3 :(得分:0)

你的方法效率不高。您可以尝试使用HashSet解决此问题。我们的想法是通过矩阵,对于每个单元格,你有两个条件:

  1. Set中存在值,在这种情况下,将matrix[i, j]设置为0
  2. Set中没有Valus,在这种情况下将其添加到Set