使用逻辑OR对多个属性进行分组

时间:2018-01-12 01:01:24

标签: c# linq join group-by logical-operators

我有一个具有多个属性的类,其中我对两个属性感兴趣。请在以下示例中说PropAPropB

public class GroupByOR
{
    public string PropA { get; set; }
    public string PropB { get; set; }
    public int SomeNumber { get; set; }
    public GroupByOR(string a, string b, int num) { PropA = a; PropB = b; SomeNumber = num; }
}

我想将此类对象的列表分组,如果 <{strong> PropAPropB <{strong> List<GroupByOR> list = new List<GroupByOR> { new GroupByOR("CA", "NY", 1), // Item 1 new GroupByOR("CA", "OR", 2), // Item 2 new GroupByOR("NY", "OR", 5) // Item 3 }; AND相匹配,则该项目的条件应属于某个组。

例如,假设我的列表如下所示:

join

然后我想要的结果就是:

  

第1组:第1项和第2项(基于CA)

     

第2组:第1项和第3项(基于纽约)

     

第3组:第2项和第3项(基于OR)

环顾四周,我发现了this以及其他许多示例,但它们似乎都专注于按多个属性进行分组,但使用data = self.http_pool.urlopen('GET', file_url, preload_content=False, retries=max_download_retries) request.add_unredirected_header(key, header) Add a header that will not be added to a redirected request. 操作。

我正在努力实现的目标是什么?

或者nauthorization: Basic <redacted>\r\n\r\n还有什么方法可以去?如果是这样,请指导我朝正确的方向发展?

1 个答案:

答案 0 :(得分:4)

你最终会得到比你开始时更多的项目,所以GroupBy并不是完整的答案。你需要这样的东西:

List<GroupByOR> list = new List<GroupByOR>
{
    new GroupByOR("CA", "NY", 1), // Item 1
    new GroupByOR("CA", "OR", 2), // Item 2
    new GroupByOR("NY", "OR", 5)  // Item 3
};

var lookupA = list.ToLookup(e => e.PropA);
var lookupB = list.ToLookup(e => e.PropB);
var keys = lookupA.Select(e => e.Key)
    .Concat(lookupB.Select(e => e.Key)).Distinct();

var result = keys.Select(e => 
    new 
    { 
        Key = e, 
        Values = lookupA[e].Concat(lookupB[e]).Distinct()
    });

这会将结果投影到一个新的匿名类型,其中Key是PropA或PropB的值,而Values是IEnumerable&lt; GroupByOr&gt;所有匹配元素。

编辑:代码演练

前两个linq行使用给定的键从枚举中进行查找(实际上是多值字典)。这些可以枚举为IEnumerable&lt; IGrouping&lt; TKey,TValue&gt;&gt;,但也可用于高效查找。

var lookupA = list.ToLookup(e => e.PropA);
var lookupB = list.ToLookup(e => e.PropB);

下一行是查找PropA和PropB的所有不同值(使用查找,但也可以返回到列表中)。

var keys = lookupA.Select(e => e.Key).Concat(lookupB.Select(e => e.Key)).Distinct();

最后一行是使用不同的键,并从propA查找和propB查找中获取匹配的枚举,然后将它们连接起来,并且(现在我发现了另一个错误)对它们进行了重复删除。

select语句产生一个匿名类型 - 这些类型不能被明确引用,但可以分配给var并且可以枚举它们。如果要存储结果值,则必须创建非匿名类型。

var result = keys.Select(e => 
    new 
    { 
        Key = e, 
        Values = lookupA[e].Concat(lookupB[e]).Distinct()
    });

编辑:输出

CA
    Values: (PropA: CA, PropB: NY, SomeNumber: 1) (PropA: CA, PropB: OR, SomeNumber: 2)
NY
    Values: (PropA: NY, PropB: OR, SomeNumber: 5) (PropA: CA, PropB: NY, SomeNumber: 1)
OR
    Values: (PropA: CA, PropB: OR, SomeNumber: 2) (PropA: NY, PropB: OR, SomeNumber: 5)