如何在数组中查找重复项并显示它们出现的次数?

32

我正在编写一段代码,用于从数组中打印出重复的整数及其出现次数。我不允许使用LINQ,只能使用简单的代码。我认为我已经接近成功了,但是对如何获得正确的输出感到困惑:

class Program
{
    static void Main(string[] args)
    {              
        int[] array = { 10, 5, 10, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12 };
        int count = 1;
        for (int i = 0; i < array.Length; i++)
        {
            for (int j = i; j < array.Length - 1 ; j++)
            {

               if(array[j] == array[j+1])
                  count = count + 1;
            }
            Console.WriteLine("\t\n " + array[i] + "occurse" + count);
            Console.ReadKey();
        }
    }
}
14个回答

62

由于您不能使用LINQ,因此您可以改用集合和循环来实现:

static void Main(string[] args)
{              
    int[] array = { 10, 5, 10, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12 };
    var dict = new Dictionary<int, int>();
    
    foreach(var value in array)
    {
        // When the key is not found, "count" will be initialized to 0
        dict.TryGetValue(value, out int count);
        dict[value] = count + 1;
    }
    
    foreach(var pair in dict)
        Console.WriteLine("Value {0} occurred {1} times.", pair.Key, pair.Value);
    Console.ReadKey();
}

我通常不会在帖子中编辑代码,但我认为TryGetValue()模式更易读,而且更高效(对于读取,只需要查找一次存在的值而不是两次),所以我已经进行了编辑,而不仅仅是提出建议。如果你真的不喜欢,可以随时恢复原样。 - Peter Duniho

25

使用Group by:

int[] values = new []{1,2,3,4,5,4,4,3};

var groups = values.GroupBy(v => v);
foreach(var group in groups)
    Console.WriteLine("Value {0} has {1} items", group.Key, group.Count());

10
让我们看一个更简单的例子。 假设我们有数组{0, 0, 0, 0}
你的代码会做什么?
它首先查看第一个项目后有多少个相等的项目。 在第一个后面有三个相等的项。
然后它转到下一个项目,并查找所有在其后相等的项目。 有两个。 到目前为止,我们已经是5了,而且我们还没有完成(还有一个要添加),但整个数组中只有四个项目。
显然,我们这里有一个问题。 我们需要确保当我们搜索给定项的数组中的重复项时,我们不要再次搜索该项。 虽然有一些方法可以做到这一点,但这种基本方法似乎是相当繁琐的工作。
当然,我们可以采取完全不同的方法。 不是遍历每个项目并搜索其他相似的项目,而是我们可以循环遍历整个数组一次,并将该字符的出现次数加到计数器中。 使用Dictionary使此操作变得容易:
var dictionary = new Dictionary<int, int>();

foreach (int n in array)
{
    if (!dictionary.ContainsKey(n))
        dictionary[n] = 0;
    dictionary[n]++;
}

现在我们可以遍历字典,查看哪些值被发现超过一次:
foreach(var pair in dictionary)
    if(pair.Value > 1)
        Console.WriteLine(pair.Key);

这使得代码可读性更强,显然是正确的,并且(作为额外的好处)要比您的代码更高效,因为您可以避免多次循环遍历集合。

6
这里有一个不使用字典的答案。由于提问者表示不熟悉字典,所以这可能会让他对字典做什么有一些了解。
这个答案的缺点是你必须在数组中强制限制最大值,并且不能有负数。你实际上永远不会在真正的代码中使用这个版本。
int[] array = { 10, 5, 10, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12 };
int[] count = new int[13];

foreach(int number in array) {
    // using the index of count same way you'd use a key in a dictionary
    count[number]++;
}

foreach(int c in count) {
    int numberCount = count[c];
    if(numberCount > 0) {
        Console.WriteLine(c + " occurs " + numberCount + " times");
    }
}

4
int[] arr = { 10, 5, 10, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12 };
var result = arr.GroupBy(x => x).Select(x => new { key = x.Key, val = x.Count() });       
foreach (var item in result)
{
    if(item.val > 1)
    {                
        Console.WriteLine("Duplicate value : {0}", item.key);
        Console.WriteLine("MaxCount : {0}", item.val);
    }

}

Console.ReadLine();

2

好的,我修改了您的代码。这应该可以胜任:

class Program
{
    static void Main(string[] args)
    {
        int[] array = { 10, 5, 10, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12 };

        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 = count + 1;
            }
            Console.WriteLine("\t\n " + array[i] + " occurs " + count + " times");
        }
        Console.ReadKey();
    }
}

1
它会报告“10出现了2次”两次。 - Matt Greer
没错,它的工作原理差不多,除了它会打印出一些数值及其出现的次数超过一次。 - sunflower
是的,在这个例子中就是这样。要摆脱它,您需要使用另一个数组变量或像其他示例中所示的字典。但我没有使用除您在示例中已经使用的变量之外的任何其他变量。 - Khurram Hassan
1
我会再仔细检查一遍,但感谢你把它推进到这个阶段 :) - sunflower

1

/这是一个使用Forloop查找重复整数值的答案,它将仅返回重复的值,而不是它们出现的次数/

    public static void Main(string[] args)
    {
        //Array list to store all the duplicate values
        int[] ary = { 10, 5, 10, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12 };
        ArrayList dup = new ArrayList();

        for (int i = 0; i < ary.Length; i++)
        {
            for (int j = i + 1; j < ary.Length; j++)
            {
                if (ary[i].Equals(ary[j]))
                {
                    if (!dup.Contains(ary[i]))
                    {
                        dup.Add(ary[i]);
                    }
                }
            }
        }
        Console.WriteLine("The numbers which duplicates are");
        DisplayArray(dup);
    }
    public static void DisplayArray(ArrayList ary)
    {
        //loop through all the elements
        for (int i = 0; i < ary.Count; i++)
        {
            Console.Write(ary[i] + " ");
        }
        Console.WriteLine();
        Console.ReadKey();
    }

1
public static void FindRepeating(int[] input) 
{
    for (var i = 0; i < input.Length; i++)
    {
        var abs = Math.Abs(input[i]);

        if (input[abs] >= 0)
            input[abs] = -input[abs];
        else
            Console.Write(abs + " ");
    }
}  

0

你犯了一个小错误,使用了 J 而不是 i ...

class Program
{
    static void Main(string[] args)
    {              
        int[] array = { 10, 5, 10, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12 };
        int count = 1;
        for (int i = 0; i < array.Length; i++)
        {
            for (int j = i; j < array.Length - 1 ; j++)
            {
               if(array[i] == array[j+1])
                  count = count + 1;
            }
            Console.WriteLine("\t\n " + array[i] + "occurse" + count);
            Console.ReadKey();
        }
    }
}

0
int[] array = { 10, 5, 10, 2, 2, 3, 4, 5, 5, 7, 7, 8, 9, 7, 12, 12 };
Dictionary<int, int> duplicateNumbers = new Dictionary<int, int>();
int count=1;
for (int i = 0; i < array.Length; i++)
{
    count=1;
    if(!duplicateNumbers.ContainsKey(array[i]))
    {
        for (int j = i; j < array.Length-1; j++)
        {
            if (array[i] == array[j+1])
            {
                count++;                            
            }
        }
        if (count > 1)
        {
            duplicateNumbers.Add(array[i], count);
        }
    }
}
foreach (var num in duplicateNumbers)
{
    Console.WriteLine("Duplicate numbers, NUMBER-{0}, OCCURRENCE- {1}",num.Key,num.Value);
}

如果你要使用字典,最好正确地使用它,避免原始代码中作者遇到的O(n^2)成本。 - Peter Duniho

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接