alexey
alexey

Reputation: 8480

How to group the same values in a sequence with LINQ?

I have a sequence. For example:

new [] { 10, 1, 1, 5, 25, 45, 45, 45, 40, 100, 1, 1, 2, 2, 3 }

Now I have to remove duplicated values without changing the overall order. For the sequence above:

new [] { 10, 1, 5, 25, 45, 40, 100, 1, 2, 3 }

How to do this with LINQ?

Upvotes: 4

Views: 950

Answers (5)

Douglas
Douglas

Reputation: 54877

Did you try Distinct?

var list = new [] { 10, 20, 20, 5, 25, 45, 45, 45, 40, 100, 1, 1, 2, 2, 3 };
list = list.Distinct();

Edit: Since you apparently only want to group items with the same values when consecutive, you could use the following:

var list = new[] { 10, 1, 1, 5, 25, 45, 45, 45, 40, 100, 1, 1, 2, 2, 3 };

List<int> result = new List<int>();
foreach (int item in list)
    if (result.Any() == false || result.Last() != item)
        result.Add(item);

Upvotes: 1

Helstein
Helstein

Reputation: 330

var list = new List<int> { 10, 1, 1, 5, 25, 45, 45, 45, 40, 100, 1, 1, 2, 2, 3 };

var result = list.Where((item, index) => index == 0 || list[index - 1] != item);

Upvotes: 3

Dovydas Navickas
Dovydas Navickas

Reputation: 3591

var list = new List<int> { 10, 1, 1, 5, 25, 45, 45, 45, 40, 100, 1, 1, 2, 2, 3 };
        List<int> result = list.Where((x, index) =>
        {
            return index == 0 || x != list.ElementAt(index - 1) ? true : false;
        }).ToList();

This returns what you want. Hope it helped.

Upvotes: 3

Damith
Damith

Reputation: 63065

You can use Contains and preserve order

List<int> newList = new List<int>();

foreach (int n in numbers)
    if (newList.Count == 0 || newList.Last() != n)
       newList.Add(n);
var newArray = newList.ToArray();

OUTPUT:

10, 1, 5, 25, 45, 40, 100, 1, 2, 3

Upvotes: 1

Kendall Frey
Kendall Frey

Reputation: 44316

It may be technically possible (though I don't think you can with a one-liner) to solve this with LINQ, but I think it's more elegant to write it yourself.

public static class ExtensionMethods
{
    public static IEnumerable<T> PackGroups<T>(this IEnumerable<T> e)
    {
        T lastItem = default(T);
        bool first = true;
        foreach(T item in e)
        {
            if (!first && EqualityComparer<T>.Default.Equals(item, lastItem))
                continue;
            first = false;
            yield return item;
            lastItem = item;
        }
    }
}

You can use it like this:

int[] packed = myArray.PackGroups().ToArray();

It's unclear from the question what should be returned in the case of 1,1,2,3,3,1. Most answers given return 1,2,3, whereas mine returns 1,2,3,1.

Upvotes: 1

Related Questions