11

我目前有一个IEnumerable<MyObject>whereMyObject有属性String Namelong Value.

如果我在 Enumerable 中有 10 个实例MyObject,每个实例都有不同的名称和值,除了一个与另一个同名。

.NET(或 LINQ)是否有一个内置方法,可以让我找到重复项,如果可能,合并Value属性,以便最终在可枚举中只有 9 个元素,每个元素都有一个不同Name的元素副本的Value等于其自身和副本的总和。

到目前为止,我发现唯一的方法是遍历整个IEnumerable并查找重复项并生成一个新IEnumerable的独特项目,但这似乎不整洁且缓慢。

4

4 回答 4

17

您可以按名称和项目结果将项目分组到“合并”对象:

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

更新:另一种选择,如果不需要新的 MyObject 实例化(例如,您在此类中有许多属性,或者您应该保留引用),那么您可以将聚合与组中的第一项用作累加器:

objects.GroupBy(o => o.Name)
       .Select(g => g.Skip(1).Aggregate(
                        g.First(), (a, o) => { a.Value += o.Value; return a; }));
于 2013-09-09T10:57:42.440 回答
8
list.GroupBy(e => e.Name).Select(group => new MyObject
    {
        Name = group.Key,
        Value = group.Sum(e => e.Value)
    }
)

更新:
另一个变种:

list.GroupBy(
    e => e.Name,
    e => e,
    (name, group) => group.Aggregate((result, e) =>
        {
            result.Value += e.Value;
            return result;
        }
    )
)
于 2013-09-09T10:58:35.870 回答
3

我不知道单一的方法解决方案,但怎么样:

set.GroupBy(g=>g.Name).Select(g=> new MyObject{Name=g.Key, Value=g.Sum(i=>i.Value)});
于 2013-09-09T10:59:05.180 回答
1

实现接口 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);
    }**
}
于 2013-09-09T11:05:21.613 回答