Si tous les éléments d'une liste ont la même valeur, alors je dois utiliser cette valeur, sinon je dois utiliser une «otherValue». Je ne peux pas penser à une manière simple et claire de faire cela.
Si tous les éléments d'une liste ont la même valeur, alors je dois utiliser cette valeur, sinon je dois utiliser une «otherValue». Je ne peux pas penser à une manière simple et claire de faire cela.
Réponses:
var val = yyy.First().Value;
return yyy.All(x=>x.Value == val) ? val : otherValue;
La manière la plus propre que je puisse imaginer. Vous pouvez en faire une ligne unique en insérant val, mais First () serait évalué n fois, doublant le temps d'exécution.
Pour incorporer le comportement "ensemble vide" spécifié dans les commentaires, il vous suffit d'ajouter une ligne supplémentaire avant les deux ci-dessus:
if(yyy == null || !yyy.Any()) return otherValue;
.Any
permettrait à l'énumération de s'arrêter tôt dans les cas où les valeurs diffèrent?
All
se terminera dès qu'il atteindra un élément x
de la séquence pour laquelle x.Value != val
. De même, Any(x => x.Value != val)
se terminerait dès qu'il atteint un élément x
de la séquence pour laquelle x.Value != val
. Autrement dit, les deux All
et Any
présentent un "court-circuit" analogue à &&
et ||
(qui est effectivement ce que All
et Any
sont).
return yyy.Skip(1).All(x=>x.Value == val) ? val : otherValue;
Bon test rapide pour tous égaux:
collection.Distinct().Count() == 1
Class
, bien que cela devrait fonctionner avec les structures. Idéal pour une liste de primitifs, cependant.
collection.Distinct().Count() <= 1
si vous souhaitez autoriser les collections vides.
Distinct
ne traversera pas du tout la collection, et Count
fera un parcours via Distinct
l'itérateur de.
Bien que vous puissiez certainement construire un tel appareil à partir d'opérateurs de séquence existants, je serais dans ce cas enclin à écrire celui-ci en tant qu'opérateur de séquence personnalisé. Quelque chose comme:
// Returns "other" if the list is empty.
// Returns "other" if the list is non-empty and there are two different elements.
// Returns the element of the list if it is non-empty and all elements are the same.
public static int Unanimous(this IEnumerable<int> sequence, int other)
{
int? first = null;
foreach(var item in sequence)
{
if (first == null)
first = item;
else if (first.Value != item)
return other;
}
return first ?? other;
}
C'est assez clair, court, couvre tous les cas et ne crée pas inutilement des itérations supplémentaires de la séquence.
Faire de cela une méthode générique qui fonctionne IEnumerable<T>
est laissé comme un exercice. :-)
other
lorsque la null
réponse était (vraisemblablement) correcte. Disons que la fonction était T Unanimous<U, T>(this IEnumerable<U> sequence, T other)
ou une telle signature, cela la complique un peu.
return collection.All(i => i == collection.First()))
? collection.First() : otherValue;.
Ou si vous craignez d'exécuter First () pour chaque élément (ce qui pourrait être un problème de performance valide):
var first = collection.First();
return collection.All(i => i == first) ? first : otherValue;
Cela peut être tardif, mais une extension qui fonctionne pour les types valeur et référence de la même manière basée sur la réponse d'Eric:
public static partial class Extensions
{
public static Nullable<T> Unanimous<T>(this IEnumerable<Nullable<T>> sequence, Nullable<T> other, IEqualityComparer comparer = null) where T : struct, IComparable
{
object first = null;
foreach(var item in sequence)
{
if (first == null)
first = item;
else if (comparer != null && !comparer.Equals(first, item))
return other;
else if (!first.Equals(item))
return other;
}
return (Nullable<T>)first ?? other;
}
public static T Unanimous<T>(this IEnumerable<T> sequence, T other, IEqualityComparer comparer = null) where T : class, IComparable
{
object first = null;
foreach(var item in sequence)
{
if (first == null)
first = item;
else if (comparer != null && !comparer.Equals(first, item))
return other;
else if (!first.Equals(item))
return other;
}
return (T)first ?? other;
}
}
public int GetResult(List<int> list){
int first = list.First();
return list.All(x => x == first) ? first : SOME_OTHER_VALUE;
}
Une alternative à l'utilisation de LINQ:
var set = new HashSet<int>(values);
return (1 == set.Count) ? values.First() : otherValue;
J'ai trouvé que l'utilisation HashSet<T>
est plus rapide pour les listes jusqu'à ~ 6000 entiers par rapport à:
var value1 = items.First();
return values.All(v => v == value1) ? value1: otherValue;
HashSet<T>
J'ai créé une application console et trouvez que c'est initialement plus rapide que d'utiliser les instructions LINQ dans ma réponse. Cependant, si je fais cela en boucle, LINQ est plus rapide.
GetHashCode()
, ce qui est difficile à faire correctement Voir: stackoverflow.com/a/371348/2607840 pour plus de détails.
Une légère variation par rapport à l'approche simplifiée ci-dessus.
var result = yyy.Distinct().Count() == yyy.Count();
Si un tableau est de type multidimensionnel comme ci-dessous, nous devons écrire ci-dessous linq pour vérifier les données.
exemple: ici les éléments sont 0 et je vérifie que toutes les valeurs sont 0 ou non.
ip1 =
0 0 0 0
0 0 0
0 0 0 0
0 0 0 0
var value=ip1[0][0]; //got the first index value
var equalValue = ip1.Any(x=>x.Any(xy=>xy.Equals())); //check with all elements value
if(equalValue)//returns true or false
{
return "Same Numbers";
}else{
return "Different Numbers";
}