Lambda expressions - set the value of one property in a collection of objects based on the value of another property in the collection
Asked Answered
F

1

10

I'm new to lambda expressions and looking to leverage the syntax to set the value of one property in a collection based on another value in a collection

Typically I would do a loop:

class Item
{
    public string Name { get; set; }
    public string Value { get; set; }
}

void Run()
{
    Item item1 = new Item { Name = "name1" };
    Item item2 = new Item { Name = "name2" };
    Item item3 = new Item { Name = "name3" };

    Collection<Item> items = new Collection<Item>() { item1, item2, item3 };

    // This is what I want to simplify.
    for (int i = 0; i < items.Count; i++)
    {
        if (items[i].Name == "name2")
        {
            // Set the value.
            items[i].Value = "value2";
        }
    }
}
Fourposter answered 26/5, 2010 at 19:5 Comment(0)
D
20

LINQ is generally more useful for selecting data than for modifying data. However, you could write something like this:

foreach(var item in items.Where(it => it.Name == "name2")) 
  item.Value = "value2";

This first selects items that need to be modified and then modifies all of them using a standard imperative loop. You can replace the foreach loop with ForAll method that's available for lists, but I don't think this gives you any advantage:

items.Where(it => it.Name == "name2").ToList()
     .ForEach(it => it.Value = "value2");

Note that you need to add ToList in the middle, because ForEach is a .NET 2.0 feature that's available only for List<T> type - not for all IEnumerable<T> types (as other LINQ methods). If you like this approach, you can implement ForEach for IEnuerable<T>:

public static void ForEach<T>(this IEnumerable<T> en, Action<T> f) {
  foreach(var a in en) f(a);
}

// Then you can omit the `ToList` conversion in the middle 
items.Where(it => it.Name == "name2")
     .ForEach(it => it.Value = "value2");

Anyway, I'd prefer foreach loop, because that also makes it clear that you're doing some mutation - and it is useful to see this fact easily in the code.

Deuteragonist answered 26/5, 2010 at 19:9 Comment(4)
beautiful. No way around the loop then?Fourposter
@Michael Rut, the loop reads better than the ForEach method, but that's a matter of opinion. I agree with what Tomas said in his answer about the clarity of the action. However, he did show a way for you to abstract away the loop (although clearly a loop will still happen, rather you explicitly code it or not).Infernal
If i want to update db after setting the value, which one would be appropriate for lesser hit on db ?Blondellblondelle
The performance will be the same - they will all generate equal number of UPDATE statements (when you commit the changes).Deuteragonist

© 2022 - 2024 — McMap. All rights reserved.