C# 更改 List<T> 中的一些值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12986776/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 01:13:42  来源:igfitidea点击:

Change some value inside the List<T>

c#linqlambdaexpression

提问by Mitja Bonca

I have some list (where T is a custom class, and class has some properties). I would like to know how to change one or more values inside of it by using Lambda Expressions, so the result will be the same as the foreach loop bellow:

我有一些列表(其中 T 是自定义类,并且类有一些属性)。我想知道如何使用 Lambda 表达式更改其中的一个或多个值,因此结果将与下面的 foreach 循环相同:

NOTE: list contains multiple items inside (multiple rows)

注意:列表中包含多个项目(多行)

        foreach (MyClass mc in list)  
        {
            if (mc.Name == "height")
                mc.Value = 30;
        }

And this the the linq query (using Lambda expressions), but its not the same as the upper foreach loop, it only returns 1 item (one row) from the list!

这是 linq 查询(使用 Lambda 表达式),但它与上面的 foreach 循环不同,它只从列表中返回 1 个项目(一行)!

What I want is, that it returns all the items (all rows) and ONLY changes the appropriate one (the items specified in the WHERE extension method(s).

我想要的是,它返回所有项目(所有行)并且只更改适当的项目(WHERE 扩展方法中指定的项目)。

list = list.Where(w => w.Name == "height").Select(s => { s.Value = 30; return s; }).ToList();

NOTE: these 2 example are not the same! I repeat, the linq only returns 1 item (one row), and this is something I don't want, I need all items from the list as well (like foreach loop, it only do changes, but it does not remove any item).

注意:这两个示例不一样!我再说一遍,linq 只返回 1 个项目(一行),这是我不想要的,我还需要列表中的所有项目(例如 foreach 循环,它只进行更改,但不会删除任何项目) )。

采纳答案by McGarnagle

You could use ForEach, but you have to convert the IEnumerable<T>to a List<T>first.

您可以使用ForEach,但您必须先将转换IEnumerable<T>为 a List<T>

list.Where(w => w.Name == "height").ToList().ForEach(s => s.Value = 30);

回答by devdigital

You could use a projection with a statement lambda, but the original foreachloop is more readable and is editing the list in place rather than creating a new list.

您可以使用带有 lambda 语句的投影,但原始foreach循环更具可读性,并且正在就地编辑列表而不是创建新列表。

var result = list.Select(i => 
   { 
      if (i.Name == "height") i.Value = 30;
      return i; 
   }).ToList();

Extension Method

扩展方法

public static IEnumerable<MyClass> SetHeights(
    this IEnumerable<MyClass> source, int value)
{
    foreach (var item in source)
    {
       if (item.Name == "height")
       {
           item.Value = value;
       }

       yield return item;
    } 
}

var result = list.SetHeights(30).ToList();

回答by Robin V.

You can do something like this:

你可以这样做:

var newList = list.Where(w => w.Name == "height")
              .Select(s => new {s.Name, s.Value= 30 }).ToList();

But I would rather choose to use foreachbecause LINQis for querying while you want to edit the data.

但我宁愿选择使用,foreach因为LINQ是在您要编辑数据时进行查询。

回答by gmn

I'd probably go with this (I know its not pure linq), keep a reference to the original list if you want to retain all items, and you should find the updated values are in there:

我可能会这样做(我知道它不是纯 linq),如果您想保留所有项目,请保留对原始列表的引用,并且您应该找到更新的值:

 foreach (var mc in list.Where(x => x.Name == "height"))  
     mc.Value = 30;

回答by Aditya Muley

How about list.Find(x => x.Name == "height").Value = 20;This works fine. I know its an old post, but just wondered why hasn't anyone suggested this? Is there a drawback in this code?

如何list.Find(x => x.Name == "height").Value = 20;这工作得很好。我知道这是一个旧帖子,但只是想知道为什么没有人提出这个建议?这段代码有什么缺点吗?

回答by David

This is the way I would do it : saying that "list" is a <List<t>>where t is a class with a Name and a Value field; but of course you can do it with any other class type.

这就是我的做法:说“列表”是一个 <List<t>>,其中 t 是一个具有名称和值字段的类;但当然你可以用任何其他类类型来做到这一点。

    list = list.Where(c=>c.Name == "height")
        .Select( new t(){Name = c.Name, Value = 30})
        .Union(list.Where(c=> c.Name != "height"))
        .ToList();

This works perfectly ! It's a simple linq expression without any loop logic. The only thing you should be aware is that the order of the lines in the result dataset will be different from the order you had in the source dataset. So if sorting is important to you, just reproduce the same order by clauses in the final linq query.

这完美地工作!这是一个简单的 linq 表达式,没有任何循环逻辑。您唯一应该注意的是,结果数据集中的行顺序将与您在源数据集中的顺序不同。因此,如果排序对您很重要,只需在最终的 linq 查询中重现相同的 order by 子句即可。