我有以下情况
class Person
{
string Name;
int Value;
int Change;
}
List<Person> list1;
List<Person> list2;
Run Code Online (Sandbox Code Playgroud)
我需要将2个列表组合成一个新的List<Person>
,如果它是同一个人,组合记录将具有该名称,list2中的人的值,更改将是list2的值 - list1的值.如果没有重复,则更改为0
Koe*_*ers 246
这可以通过使用Linq扩展方法Union轻松完成.例如:
var mergedList = list1.Union(list2).ToList();
Run Code Online (Sandbox Code Playgroud)
这将返回一个List,其中合并了两个列表,并删除了双精度数.如果您没有像我的示例中那样在Union扩展方法中指定比较器,它将使用Person类中的默认Equals和GetHashCode方法.例如,如果您想通过比较其Name属性来比较人员,则必须覆盖这些方法以自行执行比较.检查以下代码示例以完成该操作.您必须将此代码添加到Person类.
/// <summary>
/// Checks if the provided object is equal to the current Person
/// </summary>
/// <param name="obj">Object to compare to the current Person</param>
/// <returns>True if equal, false if not</returns>
public override bool Equals(object obj)
{
// Try to cast the object to compare to to be a Person
var person = obj as Person;
return Equals(person);
}
/// <summary>
/// Returns an identifier for this instance
/// </summary>
public override int GetHashCode()
{
return Name.GetHashCode();
}
/// <summary>
/// Checks if the provided Person is equal to the current Person
/// </summary>
/// <param name="personToCompareTo">Person to compare to the current person</param>
/// <returns>True if equal, false if not</returns>
public bool Equals(Person personToCompareTo)
{
// Check if person is being compared to a non person. In that case always return false.
if (personToCompareTo == null) return false;
// If the person to compare to does not have a Name assigned yet, we can't define if it's the same. Return false.
if (string.IsNullOrEmpty(personToCompareTo.Name) return false;
// Check if both person objects contain the same Name. In that case they're assumed equal.
return Name.Equals(personToCompareTo.Name);
}
Run Code Online (Sandbox Code Playgroud)
如果您不想将Person类的默认Equals方法设置为始终使用Name来比较两个对象,您还可以编写一个使用IEqualityComparer接口的比较器类.然后,您可以将此比较器作为Linq扩展联合方法中的第二个参数.有关如何编写这种比较器方法的更多信息,请访问http://msdn.microsoft.com/en-us/library/system.collections.iequalitycomparer.aspx
Mik*_*tly 75
我注意到这个问题在2年后没有被标记为已回答 - 我认为最接近的答案是理查兹,但它可以简化为此:
list1.Concat(list2)
.ToLookup(p => p.Name)
.Select(g => g.Aggregate((p1, p2) => new Person
{
Name = p1.Name,
Value = p1.Value,
Change = p2.Value - p1.Value
}));
Run Code Online (Sandbox Code Playgroud)
虽然在任何一组中都有重复名称的情况下这不会出错.
其他一些答案建议使用联合 - 这绝对不是要走的路,因为它只会让你得到一个独特的列表,而不进行组合.
J4N*_*J4N 68
为什么你不只是使用Concat?
Concat是linq的一部分,比做一个更有效率 AddRange()
在你的情况下:
List<Person> list1 = ...
List<Person> list2 = ...
List<Person> total = list1.Concat(list2);
Run Code Online (Sandbox Code Playgroud)
小智 14
这是Linq
var mergedList = list1.Union(list2).ToList();
Run Code Online (Sandbox Code Playgroud)
这是Normaly(AddRange)
var mergedList=new List<Person>();
mergeList.AddRange(list1);
mergeList.AddRange(list2);
Run Code Online (Sandbox Code Playgroud)
这是Normaly(Foreach)
var mergedList=new List<Person>();
foreach(var item in list1)
{
mergedList.Add(item);
}
foreach(var item in list2)
{
mergedList.Add(item);
}
Run Code Online (Sandbox Code Playgroud)
这是Normaly(Foreach-Dublice)
var mergedList=new List<Person>();
foreach(var item in list1)
{
mergedList.Add(item);
}
foreach(var item in list2)
{
if(!mergedList.Contains(item))
{
mergedList.Add(item);
}
}
Run Code Online (Sandbox Code Playgroud)
Ric*_*ard 12
这样做有几件事,假设每个列表不包含重复项,Name是唯一标识符,并且两个列表都没有排序.
首先创建一个追加扩展方法来获取单个列表:
static class Ext {
public static IEnumerable<T> Append(this IEnumerable<T> source,
IEnumerable<T> second) {
foreach (T t in source) { yield return t; }
foreach (T t in second) { yield return t; }
}
}
Run Code Online (Sandbox Code Playgroud)
因此可以得到一个列表:
var oneList = list1.Append(list2);
Run Code Online (Sandbox Code Playgroud)
然后分组名称
var grouped = oneList.Group(p => p.Name);
Run Code Online (Sandbox Code Playgroud)
然后可以使用帮助程序处理每个组以一次处理一个组
public Person MergePersonGroup(IGrouping<string, Person> pGroup) {
var l = pGroup.ToList(); // Avoid multiple enumeration.
var first = l.First();
var result = new Person {
Name = first.Name,
Value = first.Value
};
if (l.Count() == 1) {
return result;
} else if (l.Count() == 2) {
result.Change = first.Value - l.Last().Value;
return result;
} else {
throw new ApplicationException("Too many " + result.Name);
}
}
Run Code Online (Sandbox Code Playgroud)
哪个可以应用于以下各个元素grouped:
var finalResult = grouped.Select(g => MergePersonGroup(g));
Run Code Online (Sandbox Code Playgroud)
(警告:未经测试.)
| 归档时间: |
|
| 查看次数: |
256682 次 |
| 最近记录: |