2015-04-16 45 views
4

我需要更新IEnumerable列表中的值。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; 

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

+7

'IEnumerable'是*只读*。你不能修改它。如果你想修改集合,那么考虑把它改为'List'。 –

+0

也许使用列表会更合适? –

+0

使用合适的类而不是字符串,甚至可以使用Tuple 或Tuple 。迭代查询的结果,第二项设置为时间戳 –

回答

12

Linq针对查询而不是更新。 LINQ查询返回基于预测的一个收集,过滤器等,所以你的选择是:

  • 保存“新”集合恢复到变量(或一个新的变量,如果需要的话):

    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更干净,不是“作弊” - 你只是在原始集合上添加投影。

2

你的第一次尝试

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

返回一个新的IEnumerable,但不改变旧的。对于使用

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

或者只是将结果存储在另一个变量中。它不必替换原来的代码,并且代码更清洁 –

+2

这里不应该进行分配;它实际上并没有做任何事情,但它给人一种错误的印象,即OP的混乱。 – Servy

+0

@Servy:你说得对。我删除它。 – Raidri

0

试试这个: -

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

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

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