C#:如何检测数组中的重复值并以每个重复值只处理一次的方式处理它们?

Sig*_*gma 20 c# for-loop

我写了这个简单的程序:

    class Program
    {
        static void Main(string[] args)
        {
            Console.Write("Number of elements in the array: ");
            int numberOfElements = int.Parse(Console.ReadLine());
            int[] array = new int[numberOfElements];
            for(int i = 0; i < numberOfElements; i++)
            {
                Console.Write($"Element no {i+1}: ");
                array[i] = int.Parse(Console.ReadLine());
            }
            for(int i = 0; i < array.Length; i++)
            {
                int count = 0;
                for(int j = 0; j < array.Length; j++)
                {
                    if(array[i] == array[j])
                    {
                        count++;
                    }
                }
                Console.WriteLine($"{array[i]} appears " + count + " times");
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

是否有任何选项可以使显示的值仅打印一次?例如,如果出现 3 次 - 消息显示 3 次。但是,当出现更多事件时,是否可以使其显示一次?

AAA*_*ddd 12

您可以使用 aGroupBy而不是for 循环

对序列的元素进行分组。

var results = array
     .GroupBy(x => x)
     .Select(x => new {Value = x, Count = x.Count()});

foreach(var g in results)
   Console.WriteLine($"{g.Value} appears {g.Count} times");
Run Code Online (Sandbox Code Playgroud)

或者另一种方法是使用 aHashSet来跟踪您显示的内容。AHashSet基本上是一个不包含重复元素的集合。该Add方法返回true,如果它可以添加一个元素或false以其他方式

HashSet<T>.Add(T) Method

如果元素被添加到 HashSet 对象,则返回 true;如果元素已经存在,则为 false。

var hashSet = new HashSet<int>();
for (int i = 0; i < array.Length; i++)
{
    int count = 0;
    for (int j = 0; j < array.Length; j++)
        if (array[i] == array[j])
            count++;

    // Add to the hashset, if the add method returns true, 
    // it means the value was uniquely added, ergo you have not displayed yet
    if (hashSet.Add(array[i]))
        Console.WriteLine($"{array[i]} appears " + count + " times");
}
Run Code Online (Sandbox Code Playgroud)

完整演示在这里


或者另一种方法是使用Dictionary. 前提是遍历数组,尝试将每个项目添加到字典中,TryAdd如果已经找到则增加

var dictionary = new Dictionary<int,int>();
foreach(var item in array)
    if(!dictionary.TryAdd(item,1))
        dictionary[item]++;
    
foreach(var item in dictionary)
    Console.WriteLine($"{item.Key} appears {item.Value} times");
Run Code Online (Sandbox Code Playgroud)

完整演示在这里


Ale*_*Leo 8

我的第一个想法与 Jon Skeet 的评论相同,因为它意味着简单。

这个想法是为我们已经计数(匹配)的值设置 null。

从开发人员的角度来看,它非常简单,并且不会偏离 OP 的代码太多。

        Console.Write("Number of elements in the array: ");
        int numberOfElements = int.Parse(Console.ReadLine());
        int?[] array = new int?[numberOfElements];
        for (int i = 0; i < numberOfElements; i++)
        {
            Console.Write($"Element no {i + 1}: ");
            array[i] = int.Parse(Console.ReadLine());
        }

        for (int i = 0; i < array.Length; i++)
        {
            int count = 0;
            int? current = array[i];

            if (array[i] != null)
            {
                for (int j = 0; j < array.Length; j++)
                {
                    if (current == array[j])
                    {
                        count++;
                        array[j] = null;
                    }
                }
                Console.WriteLine($"{current} appears " + count + " times");
            }
        }
Run Code Online (Sandbox Code Playgroud)

int?[]定义可空值类型。因此数组中的每一项都可以有一个 null 或 int 值 - 文档here


Vim*_* CK 5

使用的方法DictionaryO(n)复杂性。

Console.Write("Number of elements in the array: ");

int numberOfElements = int.Parse(Console.ReadLine());
var dictionary = new Dictionary<int, int>();

for (int i = 0; i < numberOfElements; i++)
{
    Console.Write($"Element no {i + 1}: ");
    var value = int.Parse(Console.ReadLine());
    if (!dictionary.ContainsKey(value)) dictionary.Add(value, 0);

    dictionary[value] = dictionary[value] + 1;
}

foreach (var item in dictionary)
{
    Console.WriteLine($"{item.Key} appears {item.Value} times");
}
Run Code Online (Sandbox Code Playgroud)