Question

I'm have been trying to convert the foreach statement below to a LINQ statement but can't seem to wrap my head around it. Any help would be welcome.

IDictionary<string, IDictionary<string, ICollection<string>>> Highlights { get; set; }

foreach (var r in matchingProducts.Highlights)
{
    string szKey = r.Key;
    var ar = r.Value.ToArray();
    foreach (var s in ar)
    {
        string szCat = s.Key;
        var sr = s.Value.ToArray();
        foreach (var t in sr)
        {
            string szName = t;
            //todo: update the corresponding matchingProduct records
            // using the return values from szKey, szCat, szName
        }
    }
}

matchingProducts

public class Product {
    [SolrUniqueKey("id")]
    public string Id { get; set; }

    [SolrField("sku")]
    public string SKU { get; set; }

    [SolrField("name")]
    public string Name { get; set; }

    [SolrField("manu_exact")]
    public string Manufacturer { get; set; }

    [SolrField("cat")]
    public ICollection<string> Categories { get; set; }

    [SolrField("features")]
    public ICollection<string> Features { get; set; }

    [SolrField("price")]
    public decimal Price { get; set; }

    [SolrField("popularity")]
    public int Popularity { get; set; }

    [SolrField("inStock")]
    public bool InStock { get; set; }

    [SolrField("timestamp")]
    public DateTime Timestamp { get; set; }

    [SolrField("weight")]
    public double? Weight { get; set;}
}
Was it helpful?

Solution

You could just enumerate the following LINQ query

var query = from r in Highlights
            let szKey = r.Key
            let szValue = r.Value
            from s in szValue
            let szCat = s.Key
            let sr = s.Value
            from t in sr
            let szText = t
            select new { Key = szKey, Category = szCat, Text = szText };

// or, also, you can use this small query
var query = from r in Highlights
            from s in r.Value
            from t in s.Value
            select new {Key = r.Key, Category = s.Key, Text = t};    

foreach(var element in query)
{
    ProcessUpdate(element.Key, element.Category, element.Text);
}    

OTHER TIPS

You can flatten the dictionary to the items in the innermost collection by writing

dict.Values.SelectMany(d => d.Values).SelectMany(c => c)

In these lambda expressions, d is the inner dictionary, and c is the innermost ICollection.

You can get the outer keys like this:

dict.SelectMany(kvpOuter => 
    kvpOuter.Value.SelectMany(kvpInner => 
        kvpInner.Value.Select(item => 
            new { 
                OuterKey = kvpOuter.Key,
                InnerKey = kvpInner.Key,
                Item = item,
            }
        )
    )
)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top