Update item in IEnumerable

寵の児 提交于 2020-07-18 03:35:52

问题


I need to update a value in a IEnumerable list.

Here is a brief IEnumerable example:

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

Now if I want to add a timestamp to each item, this doesnt work:

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

Neither does this:

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

I made it work like this:

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

but this somehow seems like cheating. Whats the proper way of doing this please?


回答1:


Linq is for querying, not updating. Linq queries return a new collection based on projections, filters etc. So your choices are:

  • Save the "new" collection back to the variable (or a new variable, if necessary):

    allsubdirs = allsubdirs.Select(a => a = a + "_" + DateTime.Now.ToString("hhmmss")).ToList();
    
  • Use a writable interface like IList<T> and a for loop:

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

The main difference is that Select does not modify the original collection, while the for loop does.

My opinion is that the Select is cleaner and is not "cheating" - you're just adding a projection on top of the original collection.




回答2:


Your first try

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

returns a new IEnumerable but does not change the old one. For that use

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



回答3:


D Stanley has answered it correctly. I would like to add to his answer since the title is Update item in IEnumerable implying only a single item is to be updated.

As D Stanely explained in his answer:

Linq is for querying, not updating.

and

Use a writable interface like IList and a for loop

For updating a single item, you can retrieve the index of the item to be updated and use that index to update it.

For example:

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



回答4:


Try this:-

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

If you don't want to store it in another variable, consider using ToList().




回答5:


As mentioned in the existing answers, an IEnumerable collection cannot be modified by trying to assign a new value to one of its elements.

However if the elements contained in the collection are of a mutable type, you could modify them. But for your example that is not possible because a string is immutable.

So if you want to modify the existing elements in an IEnumerable, the element itself should be a type that supports modification operations, as in the below example.

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

Then you could use it like so:

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


来源:https://stackoverflow.com/questions/29676220/update-item-in-ienumerable

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!