是通用列表与众不同

时间:2015-08-03 15:52:10

标签: c# linq

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 = materials。??

上述样品至少有一个副本,即&#34; Iron&#34;因此返回值必须为假。

3 个答案:

答案 0 :(得分:5)

像这样(Linq):

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

说明:chunk.Count() > 1可能带来开销(假设Count()返回 1234567 ,内部表示是链接列表< / em>),所以更安全的方法是检查第一个之后是否有一个项目:chunk.Skip(1).Any()

编辑:即使 Linq to Objects GroupBy()的当前实现没有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()当集合/(可能)依赖于实现时是一种很好的做法。

答案 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,因为它更清楚地表明它将采用材料类型进行比较。

答案 2 :(得分:3)

更快的方法是:

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

一旦看到重复的材料,就会停止,而不是读取整个输入以便对其进行分组。