【问题标题】:Determine the most common elements in an int array确定 int 数组中最常见的元素
【发布时间】:2014-05-26 00:07:50
【问题描述】:

我在此处找到的有关此问题的答案仅返回最常见的元素之一。

我有一个 int[10] 填充随机数(0 到 20 之间),我需要找到模式。但随机性,有时有不止一种模式,有时没有。

目前我查找模式的代码是:

int mode = numArray.GroupBy(v => v)
                    .OrderByDescending(g => g.Count())
                    .FirstOrDefault()
                    .Key;

这非常有效,但如果说 12 和 8 都出现最常见,它只显示其中一个。

【问题讨论】:

标签: c# arrays linq


【解决方案1】:

我不喜欢代码,但认为这是最有效的方法:

int temp = -1;
var mode = numArray.GroupBy(v => v)
                   .OrderByDescending(g => g.Count())
                   .TakeWhile(g => {
                         if(temp == -1)
                             temp = g.Count();
                         return temp == g.Count(); })
                   .Select(g => g.Key)
                   .ToArray();

【讨论】:

  • int mode = ... .ToArray() ?
  • @ClickRick 已更新。不错的收获。
  • @MarcinJuraszek:我认为 两次分组 是有效的,而且代码更简洁。请参阅下面的答案。
【解决方案2】:
var groups = numArray.GroupBy(v => v)
                .OrderByDescending(g => g.Count())
                .ToList();

IEnumerable<int> modes = groups.TakeWhile(g => g.Count() == groups.First().Count())
                               .Select(g => g.Key);

【讨论】:

  • TakeWhile 内部调用groups.First() 将导致整个查询一遍又一遍地运行(分组和排序)。您应该将其存储在临时变量中。
  • @MarcinJuraszek - 我将添加“ToList()”,这将导致它只使用一次。没错,它会导致容器存储在内存中,但它会是更简单的代码。这是一个简单的性能权衡。
  • @AndrewShepherd:如果您的目标是更简单的代码,那么双分组是更简洁的方法......
【解决方案3】:

一种(也许)更优雅的方法涉及两次分组,一次按值分组,然后按计数:

var modes = numArray.GroupBy(i => i)
    .GroupBy(numGroup => numGroup.Count(), numGroup => numGroup.Key)
    .OrderByDescending(supergroup => supergroup.Key)
    .First().ToArray();

【讨论】:

  • +1 当然是最少的代码,但它让我的大脑在阅读它时变成了结:-)
  • @AndrewShepherd:我会把它当作一种恭维! :) 好吧,也许它不是可读的 - 但如果最终代码仅涉及内置操作(例如分组)而不是自定义编写的比较逻辑/如果,IMO 你可能会遇到更少的错误声明/等。
  • 也许每个 lambda 参数应该有不同的名称。我读起来很困惑,因为i 的类型随着链中的每一步而变化。
  • @AndrewShepherd:重点,为了清楚起见,我重命名了参数。
【解决方案4】:

在 1 遍中完成。必须比最喜欢的答案更好!

   public class PopularNumber
    {
        private Int32[] numbers = {5, 4, 3, 32, 6, 6, 3, 3, 2, 2, 31, 1, 32, 4, 3, 4, 5, 6};

        public PopularNumber()
        {
            Dictionary<Int32,Int32> bucket = new Dictionary<Int32,Int32>();
            Int32 maxInt = Int32.MinValue;
            Int32 maxCount = 0;
            Int32 count;

            foreach (var i in numbers)
            {
                if (bucket.TryGetValue(i, out count))
                {
                    count++;
                    bucket[i] = count;
                }
                else
                {
                    count = 1;
                    bucket.Add(i,count);
                }

                if (count >= maxCount)
                {
                    maxInt = i;
                    maxCount = count;
                }

            }

            Console.WriteLine("{0},{1}",maxCount, maxInt);

        }
    }

【讨论】:

    【解决方案5】:
    static int[] GetMostCommonIntegers(int[] nums)
    {
        return nums
            .ToLookup(n => n)
            .ToLookup(l => l.Count(), l => l.Key)
            .OrderBy(l => l.Key)
            .Last() 
            .ToArray();
    }   
    

    此解决方案可以处理多个数字出现相同次数的情况:

    [1,4,5,7,1] => [1]
    [1,1,2,2,3,4,5] => [1,2]
    [6,6,6,2,2,1] => [6]
    

    【讨论】:

      猜你喜欢
      • 2015-02-21
      • 1970-01-01
      • 2019-05-25
      • 1970-01-01
      • 1970-01-01
      • 2023-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多