【问题标题】:Search all List items for specific duplicate and non duplicate values在所有列表项中搜索特定的重复值和非重复值
【发布时间】:2017-10-25 10:23:04
【问题描述】:

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

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

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

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

以下是满足所需搜索条件的对象示例:

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 也不同的地方。有谁知道如何实现这一点?

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    你已经接近了。您需要扩展每个组中的序列并通过 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复制满意的组的信息,其余为空序列。

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

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

    对于第二个示例:它将产生 -> empty sequence.

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

    如果您对 cme​​ts 有任何疑问,请告诉我。

    【讨论】:

    • 谢谢瓦西尔!这很好地完成了工作。
    【解决方案2】:

    使用你现在得到的结果,而不是检查是否有更多项目(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”,只要至少没有一个“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 更多的属性)。选择每个“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 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
    

    【讨论】:

    • 感谢您的回答,但 vasil oreshenski 排在第一位,效果很好。
    猜你喜欢
    • 2010-12-20
    • 2018-12-23
    • 1970-01-01
    • 1970-01-01
    • 2020-11-27
    • 1970-01-01
    • 2021-02-11
    • 2016-10-26
    • 1970-01-01
    相关资源
    最近更新 更多