为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
犯罪嫌疑人X 2021-06-04 05:25:13
我有一个复杂对象的列表,即class MyObject {    public bool selected;    public int id;    public string name;}List<MyObject> theObjects = functionThatSelectsObjectsFromContainer();我有一个来自另一个来源的列表,它只是给了我对象列表中的 int idList<int> idList = functionThatReturnsListOfIds();现在,对于 idList 中的每个项目,我想将selected属性设置为true。我知道我可以为一个列表设置一个 foreach,然后在另一个列表中搜索匹配的项目并以这种方式设置,但我想知道是否有一种不同的方式可能会更快。
查看完整描述

3 回答

?
慕哥9229398

TA贡献1877条经验 获得超6个赞

结论

我对下面的所有方法以及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:


1


var result = theObjects.ForEach(o => o.selected = idList.Contains(o.id) ? true : false);

或使用Joinand ForEach,我们首先使用提取匹配的项目Join,然后遍历这些项目:


2


var results = theObjects.Join(idList, o => o.id, id => id, (o, id) => o).ToList();

results.ForEach(o => o.selected = true);

或者,您可以Select与ForEach和一起使用FirstOrDefault。这可能会比其他两个慢:


3


theObjects

    .Select(o => o.id)

    .Where(i => idList.Contains(i)).ToList()

    .ForEach(i => 

        theObjects.FirstOrDefault(o => o.id == i).selected = true);

我对我发布的 3 种方法进行了一些测试,其中我们有 10000MyObject秒和 1000 个唯一 ID。我运行每种方法 1000 次,然后得到每个方法的平均值ElapsedMillliseconds。


结果是


1

8.288 毫秒


2

0.19 毫秒


3

57.342 毫秒


one = 0;

two = 0;

three = 0;


for (var i = 0; i <1000; i++) {

    RunTest();

}


oneMean = one / 1000;

twoMean = two / 1000;

threeMean = three / 1000;

在哪里


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);

    }

}

我测试了un-lucky的答案(现在最多投票),平均得分为 147.676


foreach(var obj in theObjects.Where(o => idList.Any(i=> i == o.id)))

{

    obj.selected = true;

}


查看完整回答
反对 回复 2021-06-05
?
收到一只叮咚

TA贡献1821条经验 获得超4个赞

Linq的帮助下,您可以使用WhereToListForEach来实现您所需的行为 -

theObjects.Where(x => idList.Contains(x.id)).ToList().ForEach(y => y.selected = true);


查看完整回答
反对 回复 2021-06-05
  • 3 回答
  • 0 关注
  • 150 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信