我目前有一个IEnumerable<MyObject>
,其中MyObject
的属性为String Name
和long Value
。
如果我要在Enumerable中有10个MyObject
个实例,每个实例都有不同的名称和值,除了一个与另一个具有相同名称的实例。
.NET(或LINQ)是否有内置方法允许我查找副本,如果可能的话,合并Value
属性,以便最终只有9个元素在枚举中,每个具有不同的Name
且具有重复的Value
具有等于其自身和副本之和的IEnumerable
。
到目前为止,我发现迭代整个IEnumerable
的唯一方法是查找重复项并生成新的{{1}}个唯一项目,但这似乎不整齐而且速度慢。
答案 0 :(得分: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; }));
答案 1 :(得分:7)
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;
}
)
)
答案 2 :(得分:3)
我不知道单一的方法解决方案,但是:
set.GroupBy(g=>g.Name).Select(g=> new MyObject{Name=g.Key, Value=g.Sum(i=>i.Value)});
答案 3 :(得分: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);
}**
}