问题
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 aforloop: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