Объединение повторяющихся элементов в IEnumerable

В настоящее время у меня есть IEnumerable<MyObject>, где MyObject имеет свойства String Name и long Value.

Если я должен был иметь в Enumerable, 10 экземпляров MyObject, каждый с другим именем и значением, за исключением одного с тем же именем, что и другой.

Есть ли у .NET(или LINQ) встроенный метод, который позволит мне найти дубликат и, если возможно, объединить свойство Value, чтобы в нем было всего 9 элементов, каждый из которых имеет отличается от Name, и тот, у которого был дубликат, имеет Value, равный сумме его "я" и дубликата.

До сих пор я обнаружил, что единственный способ повторить все IEnumerable и искать дубликаты и генерировать новый IEnumerable уникальных элементов, но это кажется неопрятным и медленным.

Ответ 1

Вы можете группировать элементы по имени и результатам проекта в "объединенные" объекты:

objects.GroupBy(o => o.Name)
       .Select(g => new MyObject { Name = g.Key, Value = g.Sum(o => o.Value) });

UPDATE: другой вариант, если новый экземпляр MyObject нежелателен (например, у вас есть много свойств в этом классе или вы должны ссылаться на серверы), вы можете использовать агрегацию с первым элементом в группе в качестве аккумулятора:

objects.GroupBy(o => o.Name)
       .Select(g => g.Skip(1).Aggregate(
                        g.First(), (a, o) => { a.Value += o.Value; return a; }));

Ответ 2

list.GroupBy(e => e.Name).Select(group => new MyObject
    {
        Name = group.Key,
        Value = group.Sum(e => e.Value)
    }
)

Update:
Другой вариант:

list.GroupBy(
    e => e.Name,
    e => e,
    (name, group) => group.Aggregate((result, e) =>
        {
            result.Value += e.Value;
            return result;
        }
    )
)

Ответ 3

Я не знаю ни одного решения, но как насчет:

set.GroupBy(g=>g.Name).Select(g=> new MyObject{Name=g.Key, Value=g.Sum(i=>i.Value)});

Ответ 4

Внедрить интерфейс IEquatable и использовать метод Ditinct. Как следует:

internal class Program
{
    private static void Main(string[] args)
    {
        var items = new List<MyClass>
                    {
                        new MyClass
                        {
                            Name = "Name1",
                            Value = 50
                        },
                        new MyClass
                        {
                            Name = "Name2",
                            Value = 20
                        },
                        new MyClass
                        {
                            Name = "Name3",
                            Value = 50
                        }
                    };
        var distinct = items.Distinct().ToList();
    }
}

internal class MyClass : **IEquatable<MyClass>**
{
    public String Name { get; set; }
    public int Value { get; set; }

    **public bool Equals(MyClass other)
    {
        if (ReferenceEquals(null, other))
            return false;
        if (ReferenceEquals(this, other))
            return true;
        return this.Value == other.Value;
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj))
            return false;
        if (ReferenceEquals(this, obj))
            return true;
        if (obj.GetType() != this.GetType())
            return false;
        return this.Equals((MyClass)obj);
    }

    public override int GetHashCode()
    {
        return this.Value;
    }

    public static bool operator ==(MyClass left, MyClass right)
    {
        return Equals(left, right);
    }

    public static bool operator !=(MyClass left, MyClass right)
    {
        return !Equals(left, right);
    }**
}