【问题标题】:check for duplicate objectIds in a list within a list检查列表中的列表中是否存在重复的 objectId
【发布时间】:2019-03-19 22:07:45
【问题描述】:

我正在努力思考如何解决这个问题: 我目前正在浏览一个包含引用的“buildingObjects”列表,以及另一个包含“ObjectId”的“assets”列表。

            var typeBuildingPart = new List<IfcBuildingPart> {
            new IfcBuildingPart{
                BIMId = "iojeofhwofh308ry308hi32r08yrh",
                Reference = "234",
                Assets = new List<IfcAsset> {
                    new IfcAsset{
                        ObjectID = 6111838616,
                    }
                }
            },
                            new IfcBuildingPart{
                Reference = "235",
                Assets = new List<IfcAsset> {
                    new IfcAsset{
                        ObjectID = 6111838616,
                    }
                }
            },
               new IfcBuildingPart{
                Reference = "235",
                Assets = new List<IfcAsset> {
                    new IfcAsset{
                        ObjectID = 6111838616,
                    }
                }
            },
        };

目标是遍历引用和 objectId 以检查是否存在 objectId 可能具有不同引用的任何实例(如代码 sn-p 所示,其中资产的 objectID 相同,但它们没有相同的引用,然后最后保留被引用最多的引用。 我试着做多个for循环,但最终失败了。有没有什么好的 linq 方法可以解决这个问题,或者任何指针? 谢谢!

应该有不止一种资产,但我只为每个建筑部分选择了一种来演示 ObjectId 问题

最终的结果应该是删除了引用为 234 的 ifcasset。

【问题讨论】:

  • 显示你的一些代码。否则,我们将不得不猜测您是如何尝试实施或为您实施的,这对您自己的教育不利。可以用多个for循环或者LINQ来完成,没关系。
  • 每个IfcBuildingPart总是只有一个IfcAsset吗?如果是这样,为什么要列出它们?如果没有,如果有多个会发生什么?
  • " 然后最后保留被引用最多的引用",愿我们有一个具有预期结果的minimal reproducible example。在您的示例中,不清楚您想要的女巫参考,因为每个IfcBuildingPart 都有相同的Assets
  • 通常有一个大的 IfcAssets 列表,其中有多个 objectId,上面的代码只是为了说明我想要做什么。
  • 在这个例子中我只是想删除以 234 作为参考的资产

标签: c# list linq object for-loop


【解决方案1】:

看看下面的代码是否有帮助。我创建了两个字典,它们从对象映射到引用,然后引用到对象

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
         static void Main(string[] args)
        {
            var typeBuildingPart = new List<IfcBuildingPart> {
                new IfcBuildingPart{
                    BIMId = "iojeofhwofh308ry308hi32r08yrh",
                    Reference = "234",
                    Assets = new List<IfcAsset> {
                        new IfcAsset{
                            ObjectID = 6111838616,
                        }
                    }
                },
                                new IfcBuildingPart{
                    Reference = "235",
                    Assets = new List<IfcAsset> {
                        new IfcAsset{
                            ObjectID = 6111838616,
                        }
                    }
                },
                   new IfcBuildingPart{
                    Reference = "235",
                    Assets = new List<IfcAsset> {
                        new IfcAsset{
                            ObjectID = 6111838616,
                        }
                    }
                }
             };

            var dictRefToObj = typeBuildingPart.GroupBy(x => x.Reference, y => y.Assets.Select(z => z.ObjectID))
                .ToDictionary(x => x.Key, y => y.SelectMany(z => z).GroupBy(a => a).Select(a => new { obj = a.Key, count = a.Count()}).ToList());


             var dictObjToRef = dictRefToObj.Select(x => x.Value.Select(y => new { reference = x.Key, obj = y.obj, count = y.count })).SelectMany(z => z)
                .GroupBy(x => x.obj, y => new { reference = y.reference, count = y.count})
                .ToDictionary(x => x.Key, y => new { total = y.Select(z => z.count).Sum(), references = y.Select(z => new { reference = z.reference, count = z.count}).ToList()});


        }
    }
    public class IfcBuildingPart
    {
        public string BIMId { get; set; }
        public string Reference { get; set; }
        public List<IfcAsset> Assets { get; set; }
    }
    public class IfcAsset
    {
        public long ObjectID { get; set; }
    }
}

【讨论】:

    【解决方案2】:

    首先过滤列表以仅包含至少有一个IfcAsset 与您的条件匹配的元素。在Reference 上分组并计算出现次数。这样您就可以按数量订购并取第一个。

    var data = new List<Foo> {
        new Foo{Ref="A", Bars= new List<Bar>{ new Bar {Id="Good" } } },
        new Foo{Ref="B", Bars= new List<Bar>{ new Bar {Id="NotMe" } } },
        new Foo{Ref="C", Bars= new List<Bar>{ new Bar {Id="Good" } } },
        new Foo{Ref="C", Bars= new List<Bar>{ new Bar {Id="Good" } } }
    };
    
    var result = data.Where(x => x.Bars.Any(b => b.Id == "Good"))
                     .GroupBy(x => x.Ref)
                     .Select(g => new { count = g.Count(), item=g.First() })
                     .OrderByDescending(x=> x.count)
                     .Select(x=> x.item)
                     .First();
    

    【讨论】:

    • 如果您需要所有IfcBuildingPart 与最常出现的Reference 匹配,请删除最后一个。
    猜你喜欢
    • 2018-06-19
    • 1970-01-01
    • 2022-01-12
    • 2019-05-28
    • 1970-01-01
    • 2017-06-08
    • 2012-06-15
    • 2015-10-06
    • 1970-01-01
    相关资源
    最近更新 更多