2015-08-03 4 views
3
public Material 
{ 
    public MaterialType MaterialKind {get;set;} 
} 

enum MaterialType 
{ 
    Iron, 
    Plastic, 
    Carbon, 
    Wood 
} 

У меня есть список материалов.общий список отличительный

var items = new List<Material> 
{ 
    new Material{ MaterialKind = MaterialType.Iron}, 
    new Material{ MaterialKind = MaterialType.Plastic}, 
    new Material{ MaterialKind = MaterialType.Carbon}, 
    new Material{ MaterialKind = MaterialType.Iron}, 
    new Material{ MaterialKind = MaterialType.Wood}, 
} 

Каждый тип должен иметь только один доступный максимум времени в списке материалов.

Как я пишу это:

BOOL isItemsListDistinct = материалы ??.

Вышеприведенный образец имеет по крайней мере один дубликат, который является «железом», поэтому возвращаемое значение должно быть ложным.

+0

Проверьте этот пост, это отличный способ избавиться от дубликатов с помощью linq: http://stackoverflow.com/questions/1606679/remove-duplicates-in-the-list-using-linq –

+1

Возьмите посмотрите здесь Enumerable.Distinct: https://msdn.microsoft.com/en-us/library/vstudio/bb348436(v=vs.100).aspx – ajliptak

ответ

3

Более быстрый подход будет:

var materialsSeen = new HashSet<MaterialType>(); 
var allDifferent = items.All(i => materialsSeen.Add(i.MaterialKind)); 

Это останавливается, как только он видит дубликат материала, а не читать в целом вход для того, чтобы сгруппировать его.

+0

Интересный подход ... – Pascal

5

Что-то вроде этого (Linq):

bool isItemsListDistinct = !materials 
    .GroupBy(item => item) 
    .Any(chunk => chunk.Skip(1).Any()); 

Объяснение: chunk.Count() > 1 может принести накладные (представьте себе, что Count() возвращает и внутреннее представление является связанный список), поэтому safier путь - проверить, есть ли предмет после первого: chunk.Skip(1).Any().

EDIT: Даже если текущая реализация GroupBy() в Linq к объектам не имеет проблем с Count():

http://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,7bb231e0604c79e3

internal class Grouping : IGrouping<TKey, TElement>, IList<TElement> { 
    ... 
    internal int count;  
    ... 
    // No overhead in such implementation 
    int ICollection<TElement>.Count { 
     get { return count; } 
    } 
    ... 
    } 

использованием Any(), Exists (в SQL) и т.д. вместо из Count(), когда сборка/(может быть) зависит от реализации, является хорошей практикой.

+0

Хорошее объяснение вокруг 'chunk.Skip (1) .Any() ' –

+0

Хороший ответ. Мне любопытно, не будет ли код в моем ответе выполнять только первый положительный групповой счет, или он должен будет считать все группы? –

+0

@ Ioannis Karadimas: * Linq * выполняет * ленивое * исполнение, поэтому ваш код прекращает выполнение сразу после положительной группы (т. Е. С помощью 'Count()> 1'). Проблема в том, что эта первая положительная группа может быть * очень длинной *. –

3

Это способ пойти об этом:

void Main() 
{ 
    var items = new List<Material> 
    { 
    new Material{ MaterialKind = MaterialType.Iron}, 
    new Material{ MaterialKind = MaterialType.Plastic}, 
    new Material{ MaterialKind = MaterialType.Carbon}, 
    new Material{ MaterialKind = MaterialType.Iron}, 
    new Material{ MaterialKind = MaterialType.Wood}, 
    }; 

    Material.IsItemsListDistinct(items).Dump(); 
} 

// Define other methods and classes here 
public class Material 
{ 
    public MaterialType MaterialKind {get;set;} 

    public static bool IsItemsListDistinct(IList<Material> materialsList) { 
    return materialsList.GroupBy(x => x.MaterialKind).Any(x => x.Count() > 1); 
    } 
} 

public enum MaterialType 
{ 
    Iron, 
    Plastic, 
    Carbon, 
    Wood 
} 

(Выше приведен пример LINQPad, так что расширение .Dump() не будет скомпилирован в любой другой среде)

Код, по существу группы по материалу Тип, затем спрашивает, можно ли найти одну из сгруппированных записей более одного раза.

Обратите внимание, что вы должны назвать свой метод более представительным, например IsListDistinctByMaterialType, поскольку он более четко указывает, что он использует тип материала для сравнения таким образом.

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