我有一个List<Class1>
和List<Class2>
,我想从List<Class1>
中获取项目的ID在List<Class2>
中的所有项目,反之,得到List<Class1>
中没有{strong> ID 的项目中所有来自List<Class2>
的项目。
public class Class1
{
public int Id { get; set; }
public string AnotherId { get; set; }
public decimal Price { get; set; }
}
public class Class2
{
public int Id { get; set; }
public int AnotherId { get; set; }
public string Message { get; set; }
}
我用Contains
尝试了几种解决方案,但是找不到正确的方法。
答案 0 :(得分:3)
您可以尝试这样的事情:
var result = list1.Where(x => list2.Any(y=>y.Id == x.Id))
.ToList();
即使两个列表都包含对相同类型对象的引用,Contains
也无法立即使用。如果是这种情况,您将为类实现接口IEquatable
或重写Equals
和GetHashCode
方法。只有这样Contains
才能按预期工作。
答案 1 :(得分:0)
尝试这样的事情:
foreach(var val in listClass2)
{
result.AddRange(listClass1.Where(l => l.id = val.id));
}
答案 2 :(得分:0)
执行此操作的方法有多种,最简单的方法是使用System.Linq
,Where()
,All()
和Any()
方法:
var matchingIds = list1
.Where(list1Item => list2.Any(list2Item => list2Item.Id == list1Item.Id))
.ToList();
var nonMatching = list1
.Where(list1Item => list2.All(list2Item => list2Item.Id != list1Item.Id))
.ToList();
但是使用一个简单的循环也很容易:
var matchingIds = new List<Class1>();
var nonMatching = new List<Class1>();
foreach (var list1Item in list1)
{
var foundMatch = false;
foreach (var list2Item in list2)
{
if (list2Item.Id == list1Item.Id)
{
foundMatch = true;
break;
}
}
if (foundMatch)
{
matchingIds.Add(list1Item);
}
else
{
nonMatching.Add(list1Item);
}
}
答案 3 :(得分:0)
如果列表中的项目较少,则Christos的答案是最简单的。但是,它是O(n ^ 2)算法。如果列表中有相当数量的项目(甚至数千个项目),那么该算法将大大减慢速度。让我们尝试一个示例:
List<Class1> list1 = new List<Class1>();
List<Class2> list2 = new List<Class2>();
const int ITEMS_TO_ADD = 30000;
for (int i=1; i<= ITEMS_TO_ADD; i++)
{
list1.Add(new Class1 { Id = i });
list2.Add(new Class2 { Id = i });
}
for (int i = 1; i <= ITEMS_TO_ADD; i++)
{
list1.Add(new Class1 { Id = -i });
}
Stopwatch sw = new Stopwatch();
sw.Start();
var result = list1.Where(x => list2.Any(y => y.Id == x.Id)).ToList();
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
在我的机器上,大约需要30秒。
再次,一个更好的解决方案是,如果您拥有适当大小的数据集,将是这样的:
HashSet<int> list2Keys = new HashSet<int>(list2.Select(x => x.Id));
var resultInList2 = list1.Where(x => list2Keys.Contains(x.Id)).ToList();
在我的机器上耗时约10毫秒。
当然,要使项目不在列表2中,只需将行更改为
var resultInList2 = list1.Where(x => !list2Keys.Contains(x.Id)).ToList();
这当然是O(n),而不是O(n ^ 2)