2017-02-17 4 views
2

У меня есть коллекция следующим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

Вы подозреваете, что дубликаты должны быть найдены, или вы точно знаете, что существуют дубликаты? –

+8

'ClusterData' не переопределяет' Equals' + 'GetHashCode' осмысленно. Поэтому используются 'Object.GetHashCode' и' Object.Equals', которые просто сравнивают ссылки. Если они создаются с помощью 'new', они не являются одинаковыми. –

+0

Вы хотите вернуть дубликаты или просто bool, чтобы указать, есть ли они? –

ответ

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()); 

Если FirstDuplicate является null, нет никаких скоплений, которые имеют непустое пересечение; в противном случае данные компонентов пересекаются. Если это так, то пересечение itelc можно получить следующим образом.

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

Я считаю, что нисходящее движение немного удивительно; является ли решение неправильным или слишком сложным? – Codor

+0

Большое спасибо за этот ответ, однако я встречаю исключение в пределах функции Intersect, где rhs.Data является нулевым. @Nkosi Я предполагал, что это опечатка. –

+0

@Nkosi Спасибо за комментарий. Я исправил опечатку. – Codor

Смежные вопросы