将函数应用于列表

时间:2018-05-10 04:44:23

标签: c# list

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

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

5 个答案:

答案 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); SelectForEach一起使用。这可能比其他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

结果

1

8.288 ms

2

0.19 ms

3

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)

您可以尝试以下解决方案,而不需要使用WhereContains

theObjects.ForEach(a => a.selected = idList.Exists(b => a.id == b));