更新IEnumerable中的项目

时间:2015-04-16 13:28:29

标签: c# linq

我需要更新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;

但这看起来好像在作弊。请问这样做的正确方法是什么?

5 个答案:

答案 0 :(得分:21)

Linq用于查询,而非更新。 Linq查询根据投影,过滤器等返回 new 集合。因此,您的选择是:

  • 保存&#34;新&#34;收集回变量(或必要时的新变量):

    allsubdirs = allsubdirs.Select(a => 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更清洁,而不是作弊&#34; - 您只是在原始集合的顶部添加投影。

答案 1 :(得分:2)

你的第一次尝试

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

返回新的IEnumerable,但不会更改旧的allsubdirs = allsubdirs.Select(a => a + "_" + DateTime.Now.ToString("hhmmss")).ToList(); 。为此用途

{{1}}

答案 2 :(得分:0)

试试这个: -

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

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

答案 3 :(得分:0)

如现有答案中所述,尝试为其中一个元素分配新值时,无法修改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"));

答案 4 :(得分:0)

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