C#Linq子集数据

时间:2017-02-17 15:55:42

标签: c# linq

我有一个如下的集合

public class Cluster
{
   public List<ClusterData> Clust { get; set; }
}
public class ClusterData
{
   public int id { get; set; }
   public int E { get; set; }
   public int N { get; set; }
   public List<ClusterData> Data { get; set; }
}

我正在尝试查找Clust.Data的另一个实例中存在Clust子集的数据,类似这样......

var duplicate = !cluster.Clust.Except(cluster.Clust[p].Data).Any();

然而,即使我怀疑他们应该是重复的,也永远找不到重复的东西?此逻辑是否失败,因为在与其他Clust进行比较时正在考虑Clust.Data中的嵌套列表?

下面的简单示例,我想检测到对象1有一个副本(对象2和对象5),理想情况下,将它们从集合中删除。

Master collection
--- Associated collection

object 1
--- object 1
--- object 2
--- object 5
object 2
--- object 1
--- object 2
--- object 5
object 3
--- object 3
object 4
--- object 4
--- object 5
object 5
--- object 1
--- object 2
--- object 5

请参阅下文,了解我如何将这些收藏品彼此关联

 for (int p = 0; p < cluster.Clust.Count; p++)
 {
     cluster.Clust[p].Data = new List<ClusterData>();
     for (int l = 0; l < cluster.Clust.Count; l++)
     {
         //Logic logic logic
         cluster.Clust[p].Data.Add(cluster.Clust[l]);
     }
 }

1 个答案:

答案 0 :(得分:2)

首先,为方便起见,定义一个函数,它返回两个集群的子节点的交集。

IEnumerable<ClusterData> Intersect(ClusterData lhs, ClusterData rhs)
{
    return (null != lhs && null != rhs) ? lhs.Data.Intersect(rhs.Data)
                                        : Enumerable<ClusterData>.Empty();
}

接下来可以加入簇序列,使用上面定义的相等比较器生成所有对,包括所有对。

var AllPairs =
    cluster.Clust.Join( cluster.Clust,
                        x => true, // return true for both sides
                        y => true, // to get the full cartesian product
                        (x,y) => new Tuple<ClusterData,ClusterData>(x,y)
                      );

请注意,由于延迟执行,查询本身的制定实际上并不会生成对。接下来,我们将笛卡尔积的对角线排除如下,因为这些对不相关 - 只应评估不同聚类的对。

var DifferentPairs = AllPairs.Where( iPair => iPair.First != iPair.Second);

从这些中,我们选择第一对与其组件具有非空交叉的对。

var FirstDuplicate
    = DifferentPairs.FirstOrDefault( iPair => Intersect(iPair.First, iPair.Second).Any() );

如果FirstDuplicatenull,则没有没有交叉的群集;否则,组件&#39;数据相交。如果是这样,可以如下获得交叉点itselc。

var Sequence = Intersect(FirstDuplicate.First, FirstDuplicate.Second);