Home > front end >  Filter a list from a given list by matching the property of the other member of the list and groupin
Filter a list from a given list by matching the property of the other member of the list and groupin

Time:08-02

I am trying to Filter a list from a given list by matching the property of the other member of the list.

For example:

userList.Add(new User() { UserId = 1001, Name = "User1", PartnerId = 1004 });
userList.Add(new User() { UserId = 1002, Name = "User2", PartnerId = 1005 });
userList.Add(new User() { UserId = 1003, Name = "User3", PartnerId = 0 });
userList.Add(new User() { UserId = 1004, Name = "User4", PartnerId = 1001 });
userList.Add(new User() { UserId = 1005, Name = "User5", PartnerId = 1002 });
userList.Add(new User() { UserId = 1006, Name = "User6", PartnerId = 1008 });

The final list I am looking for after grouping is:

{ UserId = 1001, Name = "User1", PartnerId = 1004 } 
{ UserId = 1002, Name = "User2", PartnerId = 1005 } 
{ UserId = 1003, Name = "User3", PartnerId = 0 }    
{ UserId = 1006, Name = "User6", PartnerId = 1008 }

Explanation: In the above example, the first member's UserId 1001 is matching with the partnerId 1001 of the 4th member. So I want to group them into a separate list. Similarly for the member 2 and the member 5. Member 3 and member 6 has no matching for UserId and PartnerId so I want them as a separate member in the list.

I don't want "UserId = 1004 and PartnerId = 1001" as part of final list as it is same as "UserId = 1001 and PartnerId = 1004". Similarly for "UserId = 1005 and PartnerId = 1002".

I have tried the below expression however it also lists the duplicate ones i.e it adds both "UserId = 1004, PartnerId = 1001" and "UserId = 1001, PartnerId = 1004" as part of the list.

userList.GroupBy(d => userList.Any(v => v.UserId == d.PartnerId)).ToList();

Please let me know if there are any suggestions.

CodePudding user response:

In this case, you can probably group by max(UserId, PartnerId), or you could use min. You should then have 2 elements for each group barring the partnerId 0 group which in the above example would only have 1 element in the group.

CodePudding user response:

You can do something like this.

void main() {
var userList = new List<User>(); 
userList.Add(new User() { UserId = 1001, Name = "User1", PartnerId = 1004 });
userList.Add(new User() { UserId = 1002, Name = "User2", PartnerId = 1005 });
userList.Add(new User() { UserId = 1003, Name = "User3", PartnerId = 0 });
userList.Add(new User() { UserId = 1004, Name = "User4", PartnerId = 1001 });
userList.Add(new User() { UserId = 1005, Name = "User5", PartnerId = 1002 });
userList.Add(new User() { UserId = 1006, Name = "User6", PartnerId = 1008 });

var sortedUserList = new List<User>();

userList.ForEach(x => {
    var findPartners = userList.Where(p => p.PartnerId == x.UserId).FirstOrDefault();
    if(findPartners != null)
    {
        var listCheck = sortedUserList.Any(s => x.UserId == s.PartnerId);
        if(!listCheck)
            sortedUserList.Add(new User {UserId = x.UserId, Name = x.Name, PartnerId = findPartners.UserId});
    }
    else{
        sortedUserList.Add(new User {UserId = x.UserId, Name = x.Name, PartnerId = x.PartnerId});
    }

});
}
public class User
{
    public int UserId {get ;set;}
    public string Name {get ;set;}
    public int PartnerId {get ;set;}
}

This outputs: enter image description here

CodePudding user response:

I use GroupJoin for this to evaluate the different grouping sets, then filter out the duplicates that we don't want, in this case we will only take the User with the lowest UserId:

var uniqueUser = userList.GroupJoin(
         userList, 
         parent => parent.UserId,
         child => child.PartnerId, 
         (parent, children) => new 
         { 
             User = parent, 
             Partners = children.OrderBy(x => x.PartnerId) 
         })
         .Where(x => !x.Partners.Any() || x.User.UserId < x.Partners.First().UserId)
         .OrderBy(x => x.User.UserId)
         .Select(x => x.User)
         .ToList();

See this fiddle: result

Note that the OrderBy is crucial here.

  • Related