开发者

Selecting Items with the same subcollection using LINQ

Here is the pseudo case:

class parent{
   string name; //Some Property
   List<int> myValues;

   .......
}
........
//Initialize some parent classes

List<parent> parentList = new List<parent>();
parentList.add(parent123); //parent123.myValues == {1,2,3}
parentList.add(parent456); //parent456.myValues == {4,5,6}
parentList.add(parentMatch); //parentMatch.myValues == {1,2,3}

What I am aiming for is a query which retrieves a List of parent objects where their myValues Lists are equiva开发者_开发问答lent. In this case it would return parent123 and parentMatch.


So you can wrap the logic up and just use GroupBy if you implement an IEqualityComparer:

class IntegerListComparer : IEqualityComparer<List<int>>
{
    #region IEqualityComparer<List<int>> Members

    public bool Equals(List<int> x, List<int> y)
    {
        //bool xContainsY = y.All(i => x.Contains(i));
        //bool yContainsX = x.All(i => y.Contains(i));
        //return xContainsY && yContainsX;
        return x.SequenceEqual(y);
    }

    public int GetHashCode(List<int> obj)
    {
        return 0;
    }

    #endregion
}

Call it like so:

var results = list
    .GroupBy(p => p.MyValues, new IntegerListComparer())
    .Where(g => g.Count() > 1)
    .SelectMany(g => g);


Very silly solution:

var groups = list.GroupBy(p => string.Join(",", p.list.Select(i => i.ToString()).ToArray()))
                    .Where(x => x.Count() > 1).ToList();

Result:

an IEnumerable of groups containing parent objects having list with same int (in the same order).

If you need to match list of elements in any order (i.e. 1,2,3 == 3,1,2), just change p.list to p.list.OrderBy(x => x).

Plus, if you're targeting framework 4.0, you can avoid ToArray and ToString


EDIT:

added a where to filter single-occurrence groups.

Now if you have these parents:

parent  A  1,2,3
parent  B  1,2,3
parent  C  1,2,3
parent  D  4,5,6
parent  E  4,5,6
parent  F  7,8,9

it returns:

(A,B,C) - (D,E)


Try this:

var matches = (from p1 in parentList
               from p2 in parentList
               let c1 = p1.myValues
               let c2 = p2.myValues
               where p1 != p2 &&
                     c1.All(child => c2.Contains(child)) &&
                     c2.All(child => c1.Contains(child))
               select p1).Distinct();
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜