Home > database >  C# Linq query to join two lists and assign the result to new list
C# Linq query to join two lists and assign the result to new list

Time:03-04

First model:

public class Group
{
    public string Name { get; set; } 
    public string Sid { get; set; }
}

Second model:

public class GuidelinesWorkTeam
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Sid { get; set; }
    public bool Active { get; set; }
}

I have this method:

public IEnumerable<GuidelinesWorkTeam> GetWorkTeamsWhereChangeName(
       IEnumerable<Group> adGroups,
       IEnumerable<GuidelinesWorkTeam> gwtItems)
    {
        return gwtItems.Where(gwtItem => adGroups.Any(adGroup => gwtItem.Sid == adGroup.Sid && gwtItem.Name != adGroup.Name));
    }

adGroups input

Object Name Sid
[0] WorkTeam1 Sid1
[1] WorkTeam3 Sid2

gwtItems input

Object Id Name Sid Active
[0] 1 WorkTeam1 Sid1 true
[1] 2 WorkTeam2 Sid2 true

desired result

Object Id Name Sid Active
[0] 2 WorkTeam3 Sid2 true

Demo is here

I need to return an IEnumerable<GuidelinesWorkTeam> (Or other IEnumerable, because I need only adGroup.Name and gwtItem.Id) element if they meet the above criteria, but replacing gwtItem.Name with adGroup.Name.

How can I do that?

CodePudding user response:

Based on my understanding of your question, I would like to propose two different approaches to solve it:

  • filtering the items in adGroups before associating the adGroups items with the gwtItems items
  • (filtering the items in gwtItems as you have already done, and then) associating the gwtItems items with the adGroups items

Depending on which variable (adGroups or gwtItems) benefits most from being filtered initially, you may choose which approach fits your use case best.

Filtering the adGroups items, then associating them with the gwtItems items

Here, all applicable items from adGroups are grouped by Sid before each Sid-based grouping is associated with items from gwtItems based on the gwtItem's Sid value. After associating adGroups groupings and gwtItems with equal Sid (and unequal Name, due to the initial filtering of adGroups) using .Join(), we select each associated adGroup and gwtItem pair's adGroup.Name and gwtItem.Id in a tuple and use SelectMany() to flatten the collection (from a IEnumerable<IEnumerable< * >> to a IEnumerable< * >).

public IEnumerable<( string Name, int Id )> GetWorkTeamsWhereChangeName(
    IEnumerable<Group> adGroups,
    IEnumerable<GuidelinesWorkTeam> gwtItems)
{
    return adGroups
        .Where(adGroup => gwtItems.Any(gwtItem => 
            gwtItem.Sid == adGroup.Sid &&
            gwtItem.Name != adGroup.Name))
        .GroupBy(adGroup => adGroup.Sid)
        .Join(gwtItems,
            grouping => grouping.Key,
            gwtItem => gwtItem.Sid,
            ( grouping, gwtItem ) => grouping
                .Select(adGroup => ( adGroup.Name, gwtItem.Id )))
        .SelectMany(_ => _);
}

Associating the gwtItems items with the adGroups items (after filtering the gwtItems first)

Here, the items from gwtItems are first associated with the items from adGroups based on the Sid property from the respective classes, using .Join() before a tuple containing relevant information is returned from the .Join() operation; then, only the associated items that actually have different names are selected and converted to a simpler tuple.

Your original filtering should possibly be included if it is probable that it will filter out many items from gwtItems; but it shouldn't be necessary to obtain the desired result.

public IEnumerable<( string Name, int Id )> GetWorkTeamsWhereChangeName(
   IEnumerable<Group> adGroups,
   IEnumerable<GuidelinesWorkTeam> gwtItems)
{
    return gwtItems
        // Original filtering
        .Where(gwtItem => adGroups.Any(adGroup => 
            gwtItem.Sid == adGroup.Sid &&
            gwtItem.Name != adGroup.Name))
        // Association and final filtering
        .Join(adGroups,
            gwtItem => gwtItem.Sid,
            adGroup => adGroup.Sid,
            ( gwtItem, adGroup ) => ( 
                ChangedName: gwtItem.Name != adGroup.Name,
                Name: adGroup.Name,
                Id: gwtItem.Id))
        .Where(workTeam => workTeam.ChangedName)
        .Select(workTeam => ( workTeam.Name, workTeam.Id ));
}
  • Related