2

Array.Distinct() leaves distinct elements. How can I remove all duplicate elements from Array including original one?

For example, given this input array:

{ Dog, Cat, Mouse, Dog, Dog, Parrot, Mouse, Hound }

I'd like to get this output:

{ Cat, Parrot, Hound }
p.s.w.g
  • 146,324
  • 30
  • 291
  • 331
VixinG
  • 1,387
  • 1
  • 17
  • 31
  • I couldn't find answer to this question on Stackoverflow & google, so why so many downvotes? – VixinG Jul 09 '14 at 22:35
  • You seem to have three answers, so it's probably me, but I don't understand what you mean. You want Dog removed? (I did not downvote btw.) – Gerben Rampaart Jul 09 '14 at 22:37

4 Answers4

10

You can use a bit of Linq:

var singles = myArray
    .GroupBy(x => x)
    .Where(g => g.Count() == 1)
    .SelectMany(g => g);

Or like this:

var singles = myArray
    .GroupBy(x => x)
    .Where(g => !g.Skip(1).Any())
    .SelectMany(g => g);
  • The GroupBy method will collect all similar elements together.
  • The Where method will filter out groups that do not meet a certain condition. I've provided two alternatives conditions, but they both do the same thing—they return true only if the group contains exactly one element:
    • g.Count() == 1 counts the number of elements in each group and returns true if the result is equal to 1.
    • !g.Skip(1).Any() returns true if there are no elements after the first. This is actually marginally more efficient than g.Count() == 1 because it doesn't require enumerating all elements in the group, but it's a bit confusing to some readers, so think twice before introducing this in production code.
  • Finally, SelectMany will return all elements from in the result collection. Since there is only one element in each group, you're left with only those elements which are not duplicated.
BartoszKP
  • 34,786
  • 15
  • 102
  • 130
p.s.w.g
  • 146,324
  • 30
  • 291
  • 331
3

You could try something like this:

Array.GroupBy(x => x).Where(x => x.Count() == 1).SelectMany(x => x);
Christos
  • 53,228
  • 8
  • 76
  • 108
2

Using Group by clause you can get the result.

var list = new List<string>  { "Dog", "Cat", "Mouse", "Dog", "Dog", "Parrot", "Mouse", "Hound" };


        //var list = new List<string> { "a", "b", "a", "c", "a", "b" };
        var q = (from x in list
                 group x by x into g
                 let count = g.Count()
                 where count == 1
                 orderby count descending
                 select g.Key); 
        foreach (var x in q)
        {
            Console.WriteLine(x);
        }
1
myList.Where(i => myList.Count(j => j == i) < 2);

Note that this relies on the == operator being a good enough comparison (though you could replace it with whatever comparison you want). It also isn't very efficient, though I doubt any of the other answers will be either.

This works by restricting the result to elements that do not appear more than once in the source list.

BradleyDotNET
  • 60,462
  • 10
  • 96
  • 117
  • Whereas this will work, it will take a very long time on larger lists because it has to go through the entire list for every item. – Jim Mischel Jul 09 '14 at 22:55
  • @JimMischel, Yes it absolutely has that problem. The group by approach is much more efficient, but I didn't come up with a working one in time :) – BradleyDotNET Jul 09 '14 at 23:04