Common list

public Material
{
  public MaterialType MaterialKind {get;set;}
}

enum MaterialType
{
   Iron,
   Plastic,
   Carbon,
   Wood
}

      

I have a list of materials.

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},
}

      

Each type should have only one available maximum time in the list of materials.

How to write it:

bool isItemsListDistinct = materials.

The above sample has at least one duplicate, which is hardware, so the return value must be false.

+3


source to share


3 answers


Faster approach:

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

      



It stops as soon as it sees duplicate material, rather than reading the entire input to group it.

+3


source


Something like this (Linq):

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

      

Explanation: chunk.Count() > 1

may cause overheads (assuming Count()

returns 1234567, and the internal representation - a linked list), so the safest way - to check whether there is an element of the first: chunk.Skip(1).Any()

.

EDIT: Even though the current implementation GroupBy()

in Linq for objects has no problem with 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; }
    }
    ...
  }

      

using Any()

, Exists

(in SQL) etc. instead Count()

, where assembly / is (maybe) implementation dependent is good practice.

+5


source


This is the way to do it:

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
}

      

(The above is Linqpad example so the extension .Dump()

won't compile in any other environment)

The code essentially groups by material type, then asks if one of the grouped records can be found more than once.

Note that you should call your method more representative, for example IsListDistinctByMaterialType

, as it more clearly indicates that it uses a material type to compare in this way.

+3


source







All Articles