0

Problem

I am trying to return a unique element from a C# array with the in-built method array.Distinct.First(). The method works for some arrays but returns an incorrect element for this array {11,11,11,14,11,11}. It gives me an output of 11 which is incorrect because the unique element in that array is supposed to 14. I know there is a way to do that with a predicate function but that is just the reason why am asking, I do not know

Code

public static int getUnique(IEnumerable<int> numbers){
return numbers.Distinct().First();
//you can bet i tried .FirstOrDefault()
//without any success
}

Any help to make that code return the correct value is highly appreciated.

5
  • 3
    That's not what distinct does Commented Sep 21, 2021 at 10:08
  • What should it return in the scenario where {11,11,11,14,11,12}, etc? Commented Sep 21, 2021 at 10:09
  • 5
    array.GroupBy(x => x).Where(x =>x.Count() == 1).First() Commented Sep 21, 2021 at 10:09
  • Okay, i need to see more of the C# docs, i thought it returns a unique element for the array. It also returns unique elements for other arrays per se Commented Sep 21, 2021 at 10:30
  • @Liam, 14 and 12 Commented Sep 21, 2021 at 10:33

5 Answers 5

3

That's not what Distinct does.

It'll return distinct elements from a sequence, thus removing the duplicates.

You only want the items that have no duplicates to begin with;

var numbers = new int[] { 11, 11, 11, 14, 11 };

foreach (var i in numbers.GroupBy(i => i).Where(g => g.Count() == 1).Select(g => g.Key))
    Console.WriteLine(i);

You obviously want the first non-duplicate value, so you'd get something like this;

var numbers = new int[] { 11, 11, 11, 14, 11 };
    
int? firstNonDuplicate = numbers.GroupBy(i => i).Where(g => g.Count() == 1).Select(g => g.Key).FirstOrDefault();
    
Console.WriteLine(firstNonDuplicate);

Be vary of your null checks here though, this just proves a point.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the help bro, can you edit to make it assign the predicate result to a single int variable which is easier to return
There you go, @KINYUATIMOTHYNJIRU
2

using distinct it will return all distinct element. Get a unique value in following way

int[] numbers = { 11, 11, 11, 14, 11 };
            Console.WriteLine(numbers.GroupBy(i => i).Where(g => g.Count() == 1).Select(g => g.Key).First());

Comments

2

Generally speaking you should group your collection by a key and then filter that by the number of containing elements:

var groupings=  numbers.GroupBy(x => x)
                       .Where(x => x.Count() == 1)
                       .Select(x => x.Key);

Now that gives you all unique numbers. Your question is a bit vague, because you want "a" unique number - not "the" unique number, so there is room for interpretation, what should happen, if there are multiple numbers.

Option 1: Just take the first result:

var uniques = numbers.GroupBy(x => x)
                       .Where(x => x.Count() == 1)
                       .Select(x => x.Key)
                       .First();

Option 1.1 Order results and take the smallest (or largest)

var uniques = numbers.GroupBy(x => x)
                       .Where(x => x.Count() == 1)
                       .Select(x => x.Key)
                       .OrderBy(x => x)
                       .First();

Option 2: Ensure there is only one unique number and throw otherwise:

var uniques = numbers.GroupBy(x => x)
                       .Where(x => x.Count() == 1)
                       .Select(x => x.Key)
                       .Single();

Be aware: If there are no unique numbers, Single() and First() will throw, where as SingleOrDefault() and FirstOrDefault() will return the default value of int, which is 0, which can lead to false results. You can consider changing it to int? to allow for null to be returned, if there are no unique numbers.

Comments

0

You can try below code.

    var numbers = new int[] { 11, 11, 11, 14, 11, 11 };
    var uniqueList = numbers.GroupBy(n => n).Where(item => item.Count() == 1).Select(item => item.Key);

    foreach (var item in uniqueList)
        Console.WriteLine(item);

Comments

0

I made a special method for you. I approached the subject somewhat primitively. Thanks to this method, you can easily find unique variables.

public static int[] getUniqiue(int[] vs)
        {
            List<int> vs1 = new List<int>(vs);
            List<int> vs2 = new List<int>(vs);
            List<int> ee = new List<int>();
            List<int> vs3 = new List<int>();
            int i = 0;
            foreach (var item in vs1)
            {
                vs2.Remove(item);
                if(vs3.Contains(item) || vs2.Contains(item))
                {
                    vs3.Add(item);
                }
                else
                {
                    ee.Add(item);
                }
                i++;
            }
            return ee.ToArray();
        }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.