在所有列表项中搜索特定的重复值和非重复值

时间:2017-10-25 10:23:05

标签: c# linq

我正在寻找可以执行以下操作的Linq查询:

  1. 对于List中的每个对象,检查是否有任何对象将2个字段设置为相同的值

  2. 对于标识的每个重复集,检查第三个字段是否与其中任何一个字段不同

  3. 如果满足#1和#2,则返回true(或+计数,只是查看数据是否重复的方式)

  4. 以下是满足所需搜索标准的对象示例:

    oObject1 {    data1 = "cat",    data2 = "dog",    data3 = "DE" }
    oObject2 {    data1 = "cat",    data2 = "dog",    data3 = "FR" }
    

    以下内容不得作为“重复”返回:

    oObject3 {    data1 = "cat",    data2 = "dog",    data3 = "DE" }
    oObject4 {    data1 = "cat",    data2 = "dog",    data3 = "DE" }
    

    到目前为止,我可以使用以下查询获取重复项:

        var lDuplicates = lstObjects.GroupBy(x => new { x.data1, x.data2})
               .Where(x => x.Skip(1).Any());
    

    我需要的是扩展上面的查询以检查data3也不同的那些。有没有人知道如何实现这一目标?

2 个答案:

答案 0 :(得分:2)

你很亲密。您需要的是扩展每个组中的序列,并通过 data3 从中创建新组。

当查询趋于复杂时,我使用查询语法。如果我做对了,这可能是正确的方向。

var queryResult = 
    from obj in lstObjects
    group obj by new { obj.data1, obj.data2 } into outerGroup
    where outerGroup.Skip(1).Any()
    let additionalCheckGroup = (from g in outerGroup
                                group g by g.data3 into innerGroup
                                where innerGroup.Skip(1).Any() == false
                                select innerGroup)
    from innerGroup in additionalCheckGroup
    select new
    {
        outerKey = outerGroup.Key,
        innerKey = innerGroup.Key,
    };

查询将返回有关 data3 NOT 满足的出版物组的信息,以及其余的空序列。

所以对于第一个例子:它会产生 - >

[0]: { outerKey = {{ data1 = cat, data2 = dog }}, innerKey = "FR" }
[1]: { outerKey = {{ data1 = cat, data2 = dog }}, innerKey = "DE" }

对于第二个例子:它会产生 - > empty sequence.

注意:结果是平的,这意味着它将返回元素序列而非组,我不确定您期望的结果。

如果您对评论中有任何疑问,请与我们联系。

答案 1 :(得分:0)

使用您现在拥有的结果,而不是检查是否有更多项目(skip1-any),您可以检查是否有任何项目不等于第一项的data3。 在使用第一个data3分配变量的帮助下,在查询语法中可以更轻松地完成此操作:

  var lDuplicates = from x in lstObjects
    group x by new { x.data1, x.data2} into g //g now contains groups with unique data1 and data3 objects
    let first = g.First().data3 //assign the first data3 to an intermediate variable
    where g.Skip(1).Any(x=>x.data3 != first) //check if there are any entries that have an deviating data3
    select g;

以上选择了与条件对应的所有组(如果需要,可以在同一查询中展平)。

但这也意味着一个群体可以包含2" DE" s,只要至少有一个没有" DE"。不确定这是否是要求。要唯一地获得所有对象(展平):

  var lDuplicates = from x in lstObjects
    group x by new { x.data1, x.data2} into g //g now contains groups with unique data1 and data3 objects
    let d3 = g.Select(x=>x.data3).Distinct().ToList() //a list of unique data3 properties
    where d3.Count() > 1 //only with more than one unique data3
    from data3 in d3
    select new{g.Key.data1,g.Key.data2, data3}; //create a new object

注意,上面创建了一个 new 对象,因为对于多个匹配项,要使用哪个对象? (它可以具有比data1,data2和data3更多的属性)。要根据&data 39" -group:

选择第一个对象
  var lDuplicates = from x in lstObjects
    group x by new { x.data1, x.data2} into g //g now contains groups with unique data1 and data3 objects
    let d3 = g.GroupBy(x=>x.data3) //create a subgroup for data3 (per group g)
    where d3.Count() > 1 //only with multiple data3
    from gx in d3 //flatten d3 groups
    select gx.First(); //select the first object in the d3 subgroup