web-dev-qa-db-fra.com

Sélection d'éléments uniques à partir d'une liste en C #

Comment sélectionner les éléments uniques dans la liste {0, 1, 2, 2, 2, 3, 4, 4, 5} afin d'obtenir {0, 1, 3, 5}, en supprimant efficacement toutes les occurrences de les éléments répétés {2, 4}?

18
Ozgur Ozcitak
var numbers = new[] { 0, 1, 2, 2, 2, 3, 4, 4, 5 };

var uniqueNumbers =
    from n in numbers
    group n by n into nGroup
    where nGroup.Count() == 1
    select nGroup.Key;

// { 0, 1, 3, 5 }
31
Bryan Watts
var nums = new int{ 0...4,4,5};
var distinct = nums.Distinct();

assurez-vous que vous utilisez Linq et .NET Framework 3.5.

16
CVertex

Avec lambda ..

var all = new[] {0,1,1,2,3,4,4,4,5,6,7,8,8}.ToList();
var unique = all.GroupBy(i => i).Where(i => i.Count() == 1).Select(i=>i.Key);
12
Barbaros Alp

Solution C # 2.0:

static IEnumerable<T> GetUniques<T>(IEnumerable<T> things)
{
    Dictionary<T, int> counts = new Dictionary<T, int>();

    foreach (T item in things)
    {
        int count;
        if (counts.TryGetValue(item, out count))
            counts[item] = ++count;
        else
            counts.Add(item, 1);
    }

    foreach (KeyValuePair<T, int> kvp in counts)
    {
        if (kvp.Value == 1)
            yield return kvp.Key;
    }
}
10
Matt Howells

Voici une autre méthode qui fonctionne si vous avez des objets de type complexe dans votre liste et souhaitez obtenir les valeurs uniques d'une propriété:

var uniqueValues= myItems.Select(k => k.MyProperty)
                  .GroupBy(g => g)
                  .Where(c => c.Count() == 1)
                  .Select(k => k.Key)
                  .ToList();

Ou pour obtenir des valeurs distinctes:

var distinctValues = myItems.Select(p => p.MyProperty)
                            .Distinct()
                            .ToList();

Si votre propriété est également un type complexe, vous pouvez créer un comparateur personnalisé pour Distinct (), tel que Distinct (OrderComparer), où OrderComparer pourrait ressembler à ceci:

public class OrderComparer : IEqualityComparer<Order>
{
    public bool Equals(Order o1, Order o2)
    {
        return o1.OrderID == o2.OrderID;
    }

    public int GetHashCode(Order obj)
    {
        return obj.OrderID.GetHashCode();
    }
}
8
Ewald Stieger

Je crois que Matt voulait dire:

 static IEnumerable<T> GetUniques<T>(IEnumerable<T> things)
 {
     Dictionary<T, bool> uniques = new Dictionary<T, bool>();
     foreach (T item in things)
     {
         if (!(uniques.ContainsKey(item)))
         {
             uniques.Add(item, true);
         }
     }
     return uniques.Keys;
 }
3
Robert Rossney

Si Linq n'est pas disponible pour vous parce que vous devez prendre en charge le code hérité qui ne peut pas être mis à niveau, déclarez un dictionnaire, où le premier entier est le nombre et le second le nombre d'occurrences. Parcourez votre liste en chargeant votre dictionnaire. Lorsque vous avez terminé, parcourez votre dictionnaire en sélectionnant uniquement les éléments pour lesquels le nombre d'occurrences est 1.

3
Corey Trager

Il y a beaucoup de façons de peler un chat, mais HashSet semble fait pour la tâche.

var numbers = new[] { 0, 1, 2, 2, 2, 3, 4, 4, 5 };

HashSet<int> r = new HashSet<int>(numbers);

foreach( int i in r ) {
    Console.Write( "{0} ", i );
}

Le résultat:

0 1 2 3 4 5

2
tymtam

En .Net 2.0, je suis à peu près sûr de cette solution:

public IEnumerable<T> Distinct<T>(IEnumerable<T> source)
{
     List<T> uniques = new List<T>();
     foreach (T item in source)
     {
         if (!uniques.Contains(item)) uniques.Add(item);
     }
     return uniques;
}
0
Murilo Beltrame