Search code examples
c#linqgenericsienumerable

Select item for first list<T> by comparing with another list<Y> using linq or lambda expression


In the below code, the result returns list of bool, whereas I am expecting it to be List of BState. This should satisfy the condition mentioned in the query.

How this can be achieved. Please can someone help here?

public class Client
{
public void Execute()
{
    var response = new DataResponse();

    var BStates = new List<BState>();
    var BState = new BState() { BId = 106, CurBState = new BState() { TerminalId = 0 } };
    BStates.Add(BState);
    BState = new BState() { BId = 107, CurBState = new BState() { TerminalId = 0 } };
    BStates.Add(BState);
    BState = new BState() { BId = 108, CurBState = new BState() { TerminalId = 0 } };
    BStates.Add(BState);
    BState = new BState() { BId = 109, CurBState = new BState() { TerminalId = 0 } };
    BStates.Add(BState);
    BState = new BState() { BId = 110, CurBState = new BState() { TerminalId = 0 } };
    BStates.Add(BState);
    
    response.CurBStates = BStates;
    
    var UResources = new List<UResource>();
    var UResource = new UResource() { Name = "U1", Type = RType.A, UReason = UReason.Unknown };
    UResources.Add(UResource);
    UResource = new UResource() { Name = "U2", Type = RType.A, UReason = UReason.Unknown };
    UResources.Add(UResource);
    UResource = new UResource() { Name = "101", Type = RType.B, UReason = UReason.Unknown };
    UResources.Add(UResource);
    UResource = new UResource() { Name = "102", Type = RType.B, UReason = UReason.BCM };
    UResources.Add(UResource);
    getBotAssignmentSnapshotResponse.UResources = UResources;



    var Result = response.CurBStates
                         .Select(c => response.UResources
                         .Any(u => u.Name != c.BotId.ToString()&& 
                                   c.CurBState.TerminalId == 0 &&
                                   u.Type == RType.B &&
                                   u.UReason != UReason.BCM));
                                   
}
}

Solution

  • It seems that you need SelectMany (Projects each element of a sequence to an IEnumerable<T> and flattens the resulting sequences into one sequence.) + Where combination (Any, as you can see returns bool):

    var Result = response.CurBStates
        .SelectMany(c => response.UResources
            .Where(u => u.Name != c.BotId.ToString()&& 
                      c.CurBState.TerminalId == 0 &&
                      u.Type == RType.B &&
                      u.UReason != UReason.BCM));
    

    P.S.

    Use collection initializers instead of "manually" calling Add:

    var BStates = new List<BState>
    {
        new BState() { BId = 106, CurBState = new BState() { TerminalId = 0 } },
        new BState() { BId = 107, CurBState = new BState() { TerminalId = 0 } },
        // ...
    };
    

    UPD

    To get results exactly matching the foreach in the comments you ca do:

    var Result = response.CurBStates
        .SelectMany(c => response.UResources
            .Where(u => u.Name != c.BotId.ToString() &&
                        c.CurBState.TerminalId == 0 &&
                        u.Type == RType.B &&
                        u.UReason != UReason.BCM)
            .Select(_ => c));;
    

    If you don't need potential duplicates in the result then you need Where instead of Select in the original query:

    var Result = response.CurBStates
        .Where(c => response.UResources
            .Any(u => u.Name != c.BotId.ToString() &&
                        c.CurBState.TerminalId == 0 &&
                        u.Type == RType.B &&
                        u.UReason != UReason.BCM));