Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linq remove only one item if there are duplicate

Tags:

c#

linq

sum

I have 5 numbers i.e.: 1 1 1 2 3; I have to sum them except the minimum number, but I can remove it only one time (if the minimum occurs more than one time I have to maintain the rest). How can I do it with Linq? I thought:

var min = nums.Min();
var minSum = nums.Where(x => x != min).Sum();

But it remove all the 1s from the lists. I need a way to go out from the where if there's more than 1 occurence.

All this with Linq if it's possible.

like image 516
CRK Avatar asked Feb 16 '17 12:02

CRK


People also ask

How do I remove duplicate values in Linq?

We can remove all duplicates like this by using GroupBy and Select methods provided by LINQ . First, we group our list so that we will create groups for each name in the List. Then we use Select to only select the first objects in each group. This will result in the removal of the duplicates.

Does Linq Union remove duplicates?

Linq, acts upon 2 collections. It returns a new collection that contains the elements that are found. Union removes duplicates. So this method can be thought of as two actions: it combines the two collections and then uses Distinct() on them, removing duplicate elements.

How to remove duplicates objects from list in C#?

In order to remove duplicates from a linked list, we will use the C# built-in function Distinct(). toList() , which returns a new list after removing all duplicates from a specified list.


3 Answers

Here is a one liner which even works if your array is empty

int[] nums = { 1, 1, 1, 2, 3 };
int minSum = nums.OrderBy(x =>x).Skip(1).Sum();
like image 144
fubo Avatar answered Nov 15 '22 04:11

fubo


A simple solution would be the following, but would iterate the collection twice.

var nums = new int[]{ 1, 1, 1, 2, 3 };
var minSum = nums.Sum() - nums.Min();

For a solution that only iterates the collection once using Linq you could write:

var nums = new int[] { 1, 1, 1, 2, 3 };
var minSum = 
    nums.Aggregate(
        new {
            Min = int.MaxValue,
            Sum = 0
        },
        (accumulator, i) => new {
            Min = Math.Min(i, accumulator.Min),
            Sum = accumulator.Sum + i
        }, (accumulator) => accumulator.Sum - accumulator.Min);
like image 42
Magnus Avatar answered Nov 15 '22 05:11

Magnus


Though Magnus already seems very well, it still needs to iterate the list twice. Once to find the minium and once to find the sum.

So I just show a more verbose but therefor faster implementation:

var nums = new int[]{ 1, 1, 1, 2, 3 };
int sum = 0;
int min = int.MaxValue;
foreach (int i in nums)
{
    sum += i;
    if (i < min) min = i;
}
if (nums.Length > 0) sum -= min;

I'm not sure if a for loop maybe faster than foreach, but I think that difference should not really be measurable.


For pwas comment I add the for version again:

for(int i=0; i<nums.Length; i++)
{
    int j = nums[i];
    sum += j;
    if (j < min) min = j;
}
if (nums.Length > 0) sum -= min;
like image 5
René Vogt Avatar answered Nov 15 '22 03:11

René Vogt