【问题标题】:how to replace duplicates in row 2d array如何替换行二维数组中的重复项
【发布时间】:2022-07-14 04:07:20
【问题描述】:

我有一个 6x6 字符的二维数组,看起来像这样,我试图创建一个方法,女巫需要用“@”字符替换行中的重复项

 a b a a
 a a b c
 a a a b
 a a a a

用方法替换后应该是这样的

a b @ @
a @ b c
a @ @ b
a @ @ @

我已经尝试过这种方法,但没有结果“我需要在没有库的情况下完成这项工作”

 public  void RemoveDuplicates(char[,] array)
    {
        char symbol = '@';

        for (int i = 0; i < array.GetLength(0); i++)
        {
            for (int j = 0; j < array.GetLength(1); j++)
            {
                int temp = array[i, j];
                int next = ++temp;

                if(temp == next)
                {
                    next = symbol;
                }

            }
        }
    }

【问题讨论】:

  • “没有库”是否意味着您不能使用HashSet&lt;T&gt;
  • NO 不能用,我什至不知道 HahSet 是什么
  • “但没有结果”,因为您永远不会更改数组中的任何条目。实际上,在将字符保存到temp 之后,您需要第三个循环遍历该行的其余部分。这是一个完美的练习,首先要使用笔和纸来解决。将循环的每个迭代变量想象成指向矩阵中维度/元素的手指
  • 字符的范围是多少? a-z?还是 a-z + A-Z?还是任何Unicode字符?答案可能会改变最佳实施方式。有效率要求吗?
  • 另一个你进入的陷阱是这里从 char 到 int 的隐式转换:int temp = array[i, j]; 你实际上得到了那个 char 的 UTF-16 代码而不是索引!之后增加它时,您不会将指针移动到字符,而是更改字符本身!你在 UTF-16 代码中前进。

标签: c# asp.net .net


【解决方案1】:

您可以使用 Hashset(或列表)集合(文档:https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/collections)来存储您的重复项,如下所示:

    var hash = new HashSet<char>(); 

    for (int i = 0; i < array.GetLength(0); i++)
    {
        for (int j = 0; j < array.GetLength(1); j++)
        {
             if(!hash.Add(array[i,j])) array[i,j] = '@';
        }
        hash.Clear();
    }

或者列举如下:

    var list = new List<char>();
    
            for (int i = 0; i < array.GetLength(0); i++)
            {
                for (int j = 0; j < array.GetLength(1); j++)
                {
                    if(!list.Contains(array[i,j])) list.Add(array[i,j]);
                    else array[i,j] = '@';
                }
                list.Clear();
            }

【讨论】:

    【解决方案2】:

    可能不是最快的解决方案,但很容易理解

    考虑到这个输入

    var data = new char[,]
            {
                { 'a', 'b', 'a', 'a' },
                { 'a', 'a', 'b', 'c' },
                { 'a', 'a', 'a', 'b' },
                { 'a', 'a', 'a', 'a' },
            };
    

    使用此代码,它将逐行获取每一行,然后替换重复的值

            //for each row
            for (int i = 0; i < data.GetLength(0); i++)
            {
                //for each cell
                for (int j = 0; j < data.GetLength(1); j++)
                {
                    //for each cell compare all next cells
                    for (int k = data.GetLength(1) - 1; k > j; k--)
                    {
                        if (data[i, j] == data[i, k])
                        {
                            data[i, k] = '@';
                        }
                    }
                }
            }
    

    结果:

    a b @ @
    a @ b c
    a @ @ b
    a @ @ @
    

    PS:您可以通过迭代“data.GetLength(1) -1”来改进代码,因为最后一个单元格不能有重复。

    如果单元格的值为'@',则跳过循环,在当前代码中,您将用另一个'@'替换一些'@':D

    【讨论】:

    • 如果您能描述实际问题的开始,它将大大提高您的答案质量。
    【解决方案3】:

    目标应该是跟踪所有以前看到的字符。因此,您需要某种“集合”数据结构。最简单的方法是使用HashSet。这有一个 add 方法,可以将值添加到集合中,如果值已经在集合中,则返回 false。

    var seenCharacters = new HashSet<char>();
    for (int j = 0; j < array.GetLength(1); j++)
    {
        if(!seenCharacters.Add(array[i, j])){
             array[i, j] = symbol;
        }
    }
    

    HashSet 是框架的一部分,因此通常不会被视为“库”。

    如果现在允许,您可以使用普通数组提供类似的功能。

    var seenCharacters = new bool[(int)char.MaxValue];
    for (int j = 0; j < array.GetLength(1); j++)
    {
        var c = (int)array[i, j];
        if(seenCharacters[c]){
             array[i, j] = symbol;
        }
        seenCharacters[c] = true;
    }
    

    但我可能不会推荐这样的解决方案,因为与 hashSet 相比,它使用更多的内存。

    【讨论】:

    • "replace duplicates in row" 听起来像a 可能会重新出现在第二行而不会出现重复。
    • @JonasH 此方法替换整个数组中的重复项,我的意思是仅在行中替换
    • @emideveloper 我给你写了一条评论,正是为了这一点......因为这是一个非常重要的信息,也许你可以尝试在你的帖子中多强调一点。可能是换个例子
    • @MongZhu 现在的例子应该看起来不错!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-18
    • 2019-04-28
    • 1970-01-01
    • 2021-08-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多