tags:

views:

151

answers:

4
foreach (Feature fe in features)
{
    if (fileNames.Any(file => file.Contains(fe.FeatureName)))
    {
        fe.MatchCount = fe.MatchCount == 0 ? 1 : fe.MatchCount;
    } 
}
+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
Won't this throw the exception of "Collection was modified; enumeration operation may not execute?
Younes
@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
@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
@Danny - actually, this doesn't modify anything - there doesn't appear to be an assignment?
Marc Gravell
Ah, that looks better, thx
Marc Gravell
@Danny: You're right :).
Younes
Why the .ToList() ? Does it do anything useful in this context?
CodeInChaos
@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
+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
+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
+1 on the answer (and @Danny's comment)
Fredrik Mörk
Also debugging linq queries is a pain.
Jake
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
+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