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

Mik*_*ike 8 c# list

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

class MyObject 
{
    public bool selected;
    public int id;
    public string name;
}

List<MyObject> theObjects = functionThatSelectsObjectsFromContainer();
Run Code Online (Sandbox Code Playgroud)

我有一个来自另一个源的列表,它只是给我对象列表中的int id

List<int> idList = functionThatReturnsListOfIds();
Run Code Online (Sandbox Code Playgroud)

现在对于idList中的每个项目,我想将selected属性设置为true.我知道我可以设置一个列表的foreach,然后在另一个列表中搜索匹配项并设置它,但我想知道是否有更快的方式.

Bas*_*sie 3

结论

我对下面的所有方法以及un-lucky的答案做了一些测试,其中最快的是下面的选项2,即

var results = theObjects.Join(idList, o => o.id, id => id, (o, id) => o).ToList();
results.ForEach(o => o.selected = true);
Run Code Online (Sandbox Code Playgroud)

使用 Linq 执行此操作的另一种方法是,我们迭代theObjects并检查每个项以查看其 id 是否存在于idList

1

var result = theObjects.ForEach(o => o.selected = idList.Contains(o.id) ? true : false);
Run Code Online (Sandbox Code Playgroud)

或使用Joinand ForEach,我们首先使用提取匹配项Join,然后迭代这些项:

2

var results = theObjects.Join(idList, o => o.id, id => id, (o, id) => o).ToList();
results.ForEach(o => o.selected = true);
Run Code Online (Sandbox Code Playgroud)

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

3

theObjects
    .Select(o => o.id)
    .Where(i => idList.Contains(i)).ToList()
    .ForEach(i => 
        theObjects.FirstOrDefault(o => o.id == i).selected = true);
Run Code Online (Sandbox Code Playgroud)

我对我发布的 3 种方法做了一些测试,其中我们有 10000 个MyObjects 和 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;
Run Code Online (Sandbox Code Playgroud)

在哪里

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我测试了un-lucky的答案(目前点赞最多),它的平均分是 147.676

foreach(var obj in theObjects.Where(o => idList.Any(i=> i == o.id)))
{
    obj.selected = true;
}
Run Code Online (Sandbox Code Playgroud)