Looping though collection inside other collection and LINQ lambda expression

951 views Asked by At

Here I'm selecting descriptions from all FactoryOption with an Header of "TRANSMISSION"

tOptions = _vDetails.fOptions
                    .Where(x => (x.header != null && x.header.Value.ToUpper() == "TRANSMISSION"))
                    .Select(x => x.description)
                    .SelectMany(x => x);

If the header is null I would like to search for the header in ambiguous options which matches to "TRANSMISSION"

Something like the following :

foreach (var fOptions in _vDetails.fOptions)
{
    if (fOptions.header != null && fOptions.header.Value.ToUpper() == "TRANSMISSION")
    {
        tOptions = fOptions.description;
    }
    else if (fOptions.ambiguousOption != null)
    {
        foreach (var ambiguousOption in fOptions.ambiguousOption)
        {
            if (ambiguousOption.header != null && ambiguousOption.header.Value.ToUpper() == "TRANSMISSION")
            {
                newseq = tOptions.Concat(ambiguousOption.description);
            }
        }
    }
}

I am trying to change existing LINQ lambda expression for iterating through fOptions.ambiguousOption could someone please suggest.

2

There are 2 answers

7
RagtimeWilly On BEST ANSWER

If I'm understanding correctly I think you just want to do something like this:

var result = options.SelectMany(o => IsTransmissionHeader(o.header) ? o.description :
                                         o.ambigousOptions == null || !o.ambigousOptions.Any(x => IsTransmissionHeader(x.header)) ? new string[] { } : 
                                         o.ambigousOptions.First(x => IsTransmissionHeader(x.header)).description)
                    .Where(d => d.Any());

I added a static method to check the header:

public static bool IsTransmissionHeader(Header header)
{
    return header != null && header.Value != null && header.Value.ToUpper() == "TRANSMISSION"
}

This will return IEnumerable<string>. If you want a IEnumerable<IEnumerable<string>> change the SelectMany to Select.

EDIT:

To get all Transmission description values from ambigousOptions you need to change the last line so it looks like this:

var result = options.SelectMany(o => IsTransmissionHeader(o.header) ? o.description :
                                         o.ambigousOptions == null || !o.ambigousOptions.Any(x => IsTransmissionHeader(x.header)) ? new string[] { } :
                                         o.ambigousOptions.Where(x => IsTransmissionHeader(x.header)).SelectMany(x => x.description));
1
Mike Hixson On

This should do what you want. Here I concatenate the descriptions from FactoryOption that have a matching header with the descriptions from AmbiguousOption that have a matching header.

var descriptions = details.SelectMany(d => d.FactoryOptions.Where(f => f.Header == "TRANSMISSION").Select(f => f.Description)
    .Concat(d.FactoryOptions.SelectMany(f => f.AmbiguousOptions.Where(a => a.Header == "TRANSMISSION").Select(a => a.Description))));

Update Answer above is for when you start with a collection of Detail. If you start with a single Detail then you can do:

_vehicleDetails.FactoryOptions.Where(f => f.Header == "TRANSMISSION").Select(f => f.Description)
    .Concat(_vehicleDetails.FactoryOptions.SelectMany(f => f.AmbiguousOptions.Where(a => a.Header == "TRANSMISSION").Select(a => a.Description)));