1

Is there a way to use Linq in C# to find the majority of elements in an array? To make it a bit more complicated, if there is no majority, it should take the first element.

So for example with the array ["A", "B", "B"], the statement should evaluate to "B". And, with the array ["A", "B", "C"], the statement should evaluate to "A".

I'm sure there are a 100 other ways to do this, but curious if there is a Linq solution.

Paul
  • 3,725
  • 12
  • 50
  • 86

3 Answers3

6
var majority = array.GroupBy(x => x)
                    .MaxBy(g => g.Count())
                    .Key;

Here, I'm using MaxBy (follow the link to a version of it, but the idea is simple), which you can define as an extension method.

Community
  • 1
  • 1
jason
  • 236,483
  • 35
  • 423
  • 525
  • There's a link to a version of it on another answer. Follow the link. – jason May 10 '12 at 17:46
  • @Dave Bish: You're joking, right? Finding the max of a sequence is trivial. – jason May 10 '12 at 17:47
  • 1
    Adding an extension method, that does the same thing as GroupBy().First() ?! – Dave Bish May 10 '12 at 17:47
  • 1
    @DaveBish: It's not the same - it gives the same result, but it's more efficient. – Mark Byers May 10 '12 at 17:49
  • @Dave Bish: It's not the same thing at all! It's semantically different, and it's more efficient! First off, `GroupBy.First` is wrong, you need `GroupBy.OrderByDescending.First`. Second, `GroupBy.OrderByDescending.First` sorts the list which is `O(n log n)`. You don't need the sorted list, you just need the maximum which is `O(n)`. So, don't sort the list, just find the maximum. That's what `MaxBy` does. It's not the same thing at all, and it's really simple. – jason May 10 '12 at 17:49
  • 1
    @DaveBish Did you mean OrderBy().First() instead of GroupBy().First() in your comment? –  May 10 '12 at 17:50
5
string majority = yourArray.GroupBy(x => x)
                           .OrderByDescending(g => g.Count())
                           .First()
                           .Key;

See it working online: ideone

Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
  • 1
    This is `O(n log n)`. You can do better (avoid sorting). – jason May 10 '12 at 17:44
  • If there is no majority (count is equal for all) I don't think `OrderByDescending` is guaranteed to return the first item from the original list. – Magnus May 10 '12 at 18:02
  • 2
    @Magnus: Why do you think that? From the [docs](http://msdn.microsoft.com/en-us/library/bb534855.aspx): "This method performs a stable sort; that is, if the keys of two elements are equal, the order of the elements is preserved." – Mark Byers May 10 '12 at 18:05
  • Indeed, for equal number of strings, fails. – yo3hcv May 21 '19 at 15:43
0
var strings = new List<string>{"A", "B", "B"};

var mostCommonOrFirst = strings
    .GroupBy(s => s)
    .OrderByDescending(g => g.Count())
    .Select(g => g.Key)
    .First();
Dave Bish
  • 19,263
  • 7
  • 46
  • 63