将函数应用于列表的某些元素

我有一个复杂对象的列表,即


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,然后在另一个列表中搜索匹配的项目并以这种方式设置,但我想知道是否有一种不同的方式可能会更快。


犯罪嫌疑人X
浏览 151回答 3
3回答

慕哥9229398

结论我对下面的所有方法以及un-lucky的答案进行了一些测试,其中最快的是下面的选项2,即var results = theObjects.Join(idList, o => o.id, id => id, (o, id) => o).ToList();results.ForEach(o => o.selected = true);使用 Linq 执行此操作的另一种方法,我们在其中迭代theObjects并检查每个以查看其 id 是否存在于idList:1var result = theObjects.ForEach(o => o.selected = idList.Contains(o.id) ? true : false);或使用Joinand ForEach,我们首先使用提取匹配的项目Join,然后遍历这些项目:2var results = theObjects.Join(idList, o => o.id, id => id, (o, id) => o).ToList();results.ForEach(o => o.selected = true);或者,您可以Select与ForEach和一起使用FirstOrDefault。这可能会比其他两个慢:3theObjects&nbsp; &nbsp; .Select(o => o.id)&nbsp; &nbsp; .Where(i => idList.Contains(i)).ToList()&nbsp; &nbsp; .ForEach(i =>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; theObjects.FirstOrDefault(o => o.id == i).selected = true);我对我发布的 3 种方法进行了一些测试,其中我们有 10000MyObject秒和 1000 个唯一 ID。我运行每种方法 1000 次,然后得到每个方法的平均值ElapsedMillliseconds。结果是18.288 毫秒20.19 毫秒357.342 毫秒one = 0;two = 0;three = 0;for (var i = 0; i <1000; i++) {&nbsp; &nbsp; RunTest();}oneMean = one / 1000;twoMean = two / 1000;threeMean = three / 1000;在哪里private void RunTest(){&nbsp; &nbsp; ResetData();&nbsp; &nbsp; var stopwatch = Stopwatch.StartNew();&nbsp; &nbsp; theObjects.ForEach(o => o.selected = idList.Contains(o.id) ? true : false);&nbsp; &nbsp; stopwatch.Stop();&nbsp; &nbsp; one += stopwatch.ElapsedMilliseconds;&nbsp; &nbsp; ResetData();&nbsp; &nbsp; stopwatch = Stopwatch.StartNew();&nbsp; &nbsp; var results = theObjects.Join(idList, o => o.id, id => id, (o, id) => o).ToList();&nbsp; &nbsp; results.ForEach(o => o.selected = true);&nbsp; &nbsp; stopwatch.Stop();&nbsp; &nbsp; two += stopwatch.ElapsedMilliseconds;&nbsp; &nbsp; ResetData();&nbsp; &nbsp; stopwatch = Stopwatch.StartNew();&nbsp; &nbsp; theObjects&nbsp; &nbsp; &nbsp; &nbsp; .Select(o => o.id)&nbsp; &nbsp; &nbsp; &nbsp; .Where(i => idList.Contains(i)).ToList()&nbsp; &nbsp; &nbsp; &nbsp; .ForEach(i =>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; theObjects.FirstOrDefault(o => o.id == i).selected = true);&nbsp; &nbsp; stopwatch.Stop();&nbsp; &nbsp; three += stopwatch.ElapsedMilliseconds;}private void ResetData(){&nbsp; &nbsp; theObjects = new List<MyObject>();&nbsp; &nbsp; idList = new List<int>();&nbsp; &nbsp; var rnd = new Random();&nbsp; &nbsp; for (var i=0; i<10000; i++) {&nbsp; &nbsp; &nbsp; &nbsp; theObjects.Add(new MyObject(){id = i});&nbsp; &nbsp; }&nbsp; &nbsp; for (var i=0; i<=1000; i++) {&nbsp; &nbsp; &nbsp; &nbsp; var r = rnd.Next(0, 1000);&nbsp; &nbsp; &nbsp; &nbsp; while (idList.Contains(r)) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; r = rnd.Next(0, 10000);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; idList.Add(r);&nbsp; &nbsp; }}我测试了un-lucky的答案(现在最多投票),平均得分为 147.676foreach(var obj in theObjects.Where(o => idList.Any(i=> i == o.id))){&nbsp; &nbsp; obj.selected = true;}

收到一只叮咚

在Linq的帮助下,您可以使用Where、ToList和ForEach来实现您所需的行为 -theObjects.Where(x&nbsp;=>&nbsp;idList.Contains(x.id)).ToList().ForEach(y&nbsp;=>&nbsp;y.selected&nbsp;=&nbsp;true);
打开App,查看更多内容
随时随地看视频慕课网APP