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 theadGroups
items with thegwtItems
items - (filtering the items in
gwtItems
as you have already done, and then) associating thegwtItems
items with theadGroups
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 ));
}