我有一个复杂对象列表,即
class MyObject
{
public bool selected;
public int id;
public string name;
}
List<MyObject> theObjects = functionThatSelectsObjectsFromContainer();
我有一个来自另一个来源的列表,它只是给我对象列表中的int id
List<int> idList = functionThatReturnsListOfIds();
现在,对于idList中的每个项目,我想将selected
属性设置为true。我知道我可以设置一个列表的foreach,然后在另一个列表中搜索匹配项并设置它,但我想知道是否有更快的方式。
答案 0 :(得分:3)
我认为你可以做这样的事情来实现这个目标
foreach(var obj in theObjects.Where(o => idList.Any(i=> i == o.id)))
{
obj.selected = true;
}
答案 1 :(得分:3)
我对下面的所有方法进行了一些测试,以及非幸运的答案,其中最快的是以下选项 2 ,即< / p>
var results = theObjects.Join(idList, o => o.id, id => id, (o, id) => o).ToList();
results.ForEach(o => o.selected = true);
使用Linq执行此操作的另一种方法,我们在theObjects
处进行迭代并检查每个方法以查看其{id}中是否存在其ID:
<强> 1 强>
idList
或使用var result = theObjects.ForEach(o => o.selected = idList.Contains(o.id) ? true : false);
和Join
,我们首先使用ForEach
提取匹配项,然后围绕这些项进行迭代:
<强> 2 强>
Join
或者,您可以将var results = theObjects.Join(idList, o => o.id, id => id, (o, id) => o).ToList();
results.ForEach(o => o.selected = true);
与Select
和ForEach
一起使用。这可能比其他2慢:
第3 强>
FirstOrDefault
我对我发布的3种方法进行了一些测试,其中我们有10000 theObjects
.Select(o => o.id)
.Where(i => idList.Contains(i)).ToList()
.ForEach(i =>
theObjects.FirstOrDefault(o => o.id == i).selected = true);
个和1000个唯一ID。我运行了每个方法1000次,然后得到每个方法的平均值MyObject
。
结果
8.288 ms
0.19 ms
57.342 ms
ElapsedMillliseconds
,其中
one = 0;
two = 0;
three = 0;
for (var i = 0; i <1000; i++) {
RunTest();
}
oneMean = one / 1000;
twoMean = two / 1000;
threeMean = three / 1000;
我测试了 un-lucky 的答案(目前最热门的评价),平均得分为147.676
private void RunTest()
{
ResetData();
var stopwatch = Stopwatch.StartNew();
theObjects.ForEach(o => o.selected = idList.Contains(o.id) ? true : false);
stopwatch.Stop();
one += stopwatch.ElapsedMilliseconds;
ResetData();
stopwatch = Stopwatch.StartNew();
var results = theObjects.Join(idList, o => o.id, id => id, (o, id) => o).ToList();
results.ForEach(o => o.selected = true);
stopwatch.Stop();
two += stopwatch.ElapsedMilliseconds;
ResetData();
stopwatch = Stopwatch.StartNew();
theObjects
.Select(o => o.id)
.Where(i => idList.Contains(i)).ToList()
.ForEach(i =>
theObjects.FirstOrDefault(o => o.id == i).selected = true);
stopwatch.Stop();
three += stopwatch.ElapsedMilliseconds;
}
private void ResetData()
{
theObjects = new List<MyObject>();
idList = new List<int>();
var rnd = new Random();
for (var i=0; i<10000; i++) {
theObjects.Add(new MyObject(){id = i});
}
for (var i=0; i<=1000; i++) {
var r = rnd.Next(0, 1000);
while (idList.Contains(r)) {
r = rnd.Next(0, 10000);
}
idList.Add(r);
}
}
答案 2 :(得分:1)
在 Linq 的帮助下,您可以使用 Where , ToList 和 ForEach 来实现您所需的行为 -
theObjects.Where(x => idList.Contains(x.id)).ToList().ForEach(y => y.selected = true);
答案 3 :(得分:0)
使用linq你可以这样做
{{1}}
答案 4 :(得分:0)
您可以尝试以下解决方案,而不需要使用Where
和Contains
:
theObjects.ForEach(a => a.selected = idList.Exists(b => a.id == b));