linq 更新IEnumerable中的项

iqjalb3h  于 2023-01-28  发布在  其他
关注(0)|答案(5)|浏览(197)

我需要更新IEnumerable列表中的值。
下面是一个简单的IEnumerable示例:

IEnumerable<string> allsubdirs = new List<string>() { "a", "b", "c" };

现在,如果我想为每个项目添加时间戳,这将不起作用:

allsubdirs.Select(a => a = a + "_" + DateTime.Now.ToString("hhmmss")).ToList();

这也不适用:

foreach (var item in allsubdirs)
            item = item + "_" + DateTime.Now.ToString("hhmmss");

我是这样设计的:

IEnumerable<string> newallsubdirs = allsubdirs.Select(a => a + "_" + DateTime.Now.ToString("hhmmss")).ToList();
        allsubdirs = newallsubdirs;

但这似乎有点像作弊。请问正确的做法是什么?

lp0sw83n

lp0sw83n1#

Linq用于 * 查询 *,而不是 * 更新 *。Linq查询基于投影、过滤器等返回一个 * 新 * 集合(或源集合顶部的迭代器)。因此,您的选择是:

  • 将“new”集合保存回变量(或新变量,如有必要):
allsubdirs = allsubdirs.Select(a => a + "_" + DateTime.Now.ToString("hhmmss")).ToList();
  • 使用IList<T>之类的可写接口和for循环:
IList<string> allsubdirs = new List<string>() { "a", "b", "c" };

  for(int i=0; i<allsubdirs.Count(); i++)
      allsubdirs[i] = allsubdirs[i] + "_" + DateTime.Now.ToString("hhmmss");

主要区别在于Select * 不修改原始集合 *,而for循环修改原始集合。
我的观点是Select更干净,没有“作弊”-你只是在原来的集合上添加了一个投影。

9rnv2umw

9rnv2umw2#

D Stanley回答正确。我想补充他的答案,因为标题是Update item in IEnumerable,意味着只有一个项目要更新。
正如D Stanely在他的answer中所解释的:
Linq是用来查询的,不是用来更新的。
以及
使用IList等可写接口和for循环
要更新单个项,可以检索要更新的项的索引,并使用该索引更新该项。
例如:

IList<string> allsubdirs = new List<string>() { "a", "b", "c" };
int index = allsubdirs.IndexOf("a");
allsubdirs[index] = "d";
yebdmbv4

yebdmbv43#

你的第一次尝试

allsubdirs.Select(a => a = a + "_" + DateTime.Now.ToString("hhmmss")).ToList();

返回一个新的IEnumerable,但不改变旧的。

allsubdirs = allsubdirs.Select(a => a + "_" + DateTime.Now.ToString("hhmmss")).ToList();
bbmckpt7

bbmckpt74#

试试这个:-

var result= allsubdirs.Select(x => String.Format("{0}_{1}", x,
                                      DateTime.Now.ToString("hhmmss")));

如果您不想将其存储在另一个变量中,请考虑使用ToList()

qybjjes1

qybjjes15#

正如在现有答案中提到的,不能通过尝试为IEnumerable集合的一个元素赋新值来修改该集合。
然而,如果集合中包含的元素是可变类型的,你可以修改它们,但是对于你的例子来说,这是不可能的,因为string是不可变的。
因此,如果要修改IEnumerable中的现有元素,元素本身应该是支持修改操作的类型,如下面的示例所示。

public class MyItem
{
    private string _value;

    public MyItem(string content)
    {
        _value = content;
    }
    public void Append(string other)
    {
        _value += other;
    }
    public void ReplaceWith(Func<string, string> replacer)
    {
        _value = replacer(_value); 
    }
}

那么你可以这样使用它:

IEnumerable<MyItem> allsubdirs = new List<MyItem>() { new MyItem("a"), new MyItem("b"), new MyItem("c") };

foreach (var item in allsubdirs)
        item.Append("_" + DateTime.Now.ToString("hhmmss"));

相关问题