foreach (Feature fe in features)
{
if (fileNames.Any(file => file.Contains(fe.FeatureName)))
{
fe.MatchCount = fe.MatchCount == 0 ? 1 : fe.MatchCount;
}
}
views:
151answers:
4
+3
A:
features.Where(f => fileNames.Any(file => file.Contains(f.FeatureName)))
.ToList()
.ForEach(x => x.MatchCount = x.MatchCount == 0 ? 1 : x.MatchCount);
Danny Chen
2010-10-13 07:10:54
Won't this throw the exception of "Collection was modified; enumeration operation may not execute?
Younes
2010-10-13 07:14:14
@Younes: the collection is not modified. Properties of objects in the collection are modified (or would be; seems the assignment is missing), but the collection itself is not modified.
Fredrik Mörk
2010-10-13 07:15:46
@Younes: Will it? It's a notepad code, I didn't try it. But I think it won't throw the exception, because I cast it `ToList` first. The modification is based on the list.
Danny Chen
2010-10-13 07:17:14
@Danny - actually, this doesn't modify anything - there doesn't appear to be an assignment?
Marc Gravell
2010-10-13 07:19:02
Ah, that looks better, thx
Marc Gravell
2010-10-13 07:26:08
@Danny: You're right :).
Younes
2010-10-13 08:07:53
Why the .ToList() ? Does it do anything useful in this context?
CodeInChaos
2010-10-13 22:41:01
@CodeInChaos, `.ForEach()` is a instance method of `List<T>` and does not exist for `IEnumerable<T>`* (unless you code it yourself). The result of `.Where()` is an `IEnumerable<T>`*. (*substitute `IQueryable<T>` if appropriate.)
Anthony Pegram
2010-10-13 22:52:31
+9
A:
You are mutating the object at the end of the loop-variable, so you can't do that (cleanly) in pure LINQ. Just keep the loop; it'll be simpler to understand, but maybe it can be reduced a bit:
var qry = features.Where(fe => fe.MatchCount == 0 &&
fileNames.Any(file => file.Contains(fe.FeatureName));
foreach (Feature fe in qry) { fe.MatchCount == 1; }
Marc Gravell
2010-10-13 07:11:38
+1 I can't understand why people don't like `foreach(blabla)`, they always prefer an one-line-linq-expression, which is not readable than the `foreach` loop.
Danny Chen
2010-10-13 07:15:26
A:
Func<Feature, Feature> updateMatchCount = (fe) =>{
fe.MatchCount = fe.MatchCount == 0 ? 1 : fe.MatchCount;
return fe;
};
var updatedFeatures = from fe in features
where fileNames.Any(file => file.Contains(fe.FeatureName))
select updateMatchCount(fe);
p.revington
2010-10-13 07:32:34
+1
A:
Something worth mentioning is that materializing your query to a list, and then iterating over it again with 'ForEach' can be a pretty expensive call if your list is quite large. I would recommend adding the following extension method to give a 'ForEach' method to IEnumerable:
public static void Map<T>(this IEnumerable<T> source, Action<T> func)
{
foreach (T i in source)
func(i);
}
I call mine Map, but you can call it ForEach if you so choose. This turns Danny's answer into:
features.Where(f => fileNames.Any(file => file.Contains(f.FeatureName)))
.Map(x => x.MatchCount = x.MatchCount == 0 ? 1 : x.MatchCount);
diceguyd30
2010-10-13 20:30:27