Replacing nested foreach with LINQ; modify and update a property deep within

p.campbell picture p.campbell · Aug 26, 2009 · Viewed 31.5k times · Source

Consider the requirement to change a data member on one or more properties of an object that is 5 or 6 levels deep.

There are sub-collections that need to be iterated through to get to the property that needs inspection & modification.

Here we're calling a method that cleans the street address of a Employee. Since we're changing data within the loops, the current implementation needs a for loop to prevent the exception:

Cannot assign to "someVariable" because it is a 'foreach iteration variable'

Here's the current algorithm (obfuscated) with nested foreach and a for.

foreach (var emp in company.internalData.Emps)
{
    foreach (var addr in emp.privateData.Addresses)
    {
        int numberAddresses = addr.Items.Length;

        for (int i = 0; i < numberAddresses; i++)
        {
            //transform this street address via a static method
            if (addr.Items[i].Type =="StreetAddress")
               addr.Items[i].Text = CleanStreetAddressLine(addr.Items[i].Text);
        }
    }
}

Question: Can this algorithm be reimplemented using LINQ? The requirement is for the original collection to have its data changed by that static method call.

Update: I was thinking/leaning in the direction of a jQuery/selector type solution. I didn't specifically word this question in that way. I realize that I was over-reaching on that idea (no side-effects). Thanks to everyone! If there is such a way to perform a jQuery-like selector, please let's see it!

Answer

mmx picture mmx · Aug 26, 2009
foreach(var item in company.internalData.Emps
                        .SelectMany(emp => emp.privateData.Addresses)
                        .SelectMany(addr => addr.Items)
                        .Where(addr => addr.Type == "StreetAddress"))
     item.Text = CleanStreetAddressLine(item.Text);