Wenn alle Elemente in einer Liste denselben Wert haben, muss ich diesen Wert verwenden, andernfalls muss ich einen „anderen Wert“ verwenden. Ich kann mir keinen einfachen und klaren Weg vorstellen, dies zu tun.
Wenn alle Elemente in einer Liste denselben Wert haben, muss ich diesen Wert verwenden, andernfalls muss ich einen „anderen Wert“ verwenden. Ich kann mir keinen einfachen und klaren Weg vorstellen, dies zu tun.
Antworten:
var val = yyy.First().Value;
return yyy.All(x=>x.Value == val) ? val : otherValue;
Die sauberste Art, die ich mir vorstellen kann. Sie können es zu einem Einzeiler machen, indem Sie val einfügen, aber First () wird n-mal ausgewertet, wodurch die Ausführungszeit verdoppelt wird.
Um das in den Kommentaren angegebene Verhalten "leerer Satz" zu berücksichtigen, fügen Sie einfach eine weitere Zeile vor den beiden oben genannten hinzu:
if(yyy == null || !yyy.Any()) return otherValue;
.Any
zulassen, dass die Aufzählung in Fällen mit unterschiedlichen Werten vorzeitig beendet wird?
All
wird beendet, sobald es ein Element x
der Sequenz trifft , für das x.Value != val
. In ähnlicher Weise Any(x => x.Value != val)
würde enden, sobald es ein Element x
der Sequenz trifft , für die x.Value != val
. Das heißt, beide All
und Any
weisen einen "Kurzschluss" analog zu &&
und auf ||
(was effektiv was ist All
und Any
ist).
return yyy.Skip(1).All(x=>x.Value == val) ? val : otherValue;
Guter Schnelltest für alle gleich:
collection.Distinct().Count() == 1
Class
, obwohl es mit Strukturen funktionieren sollte. Ideal für eine Liste von Grundelementen.
collection.Distinct().Count() <= 1
wenn Sie leere Sammlungen zulassen möchten.
Distinct
wird die Sammlung überhaupt nicht durchlaufen, und es Count
wird eine Durchquerung über Distinct
den Iterator durchgeführt.
Obwohl Sie ein solches Gerät sicherlich aus vorhandenen Sequenzoperatoren erstellen können, wäre ich in diesem Fall geneigt, dieses als benutzerdefinierten Sequenzoperator zu schreiben. Etwas wie:
// 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;
}
Das ist ziemlich klar, kurz, deckt alle Fälle ab und erzeugt nicht unnötig zusätzliche Iterationen der Sequenz.
Dies zu einer generischen Methode zu machen, die funktioniert, IEnumerable<T>
bleibt als Übung übrig. :-)
other
wenn das null
tatsächlich die (vermutlich) richtige Antwort war. Angenommen, die Funktion war T Unanimous<U, T>(this IEnumerable<U> sequence, T other)
oder eine solche Signatur, die es ein wenig kompliziert.
return collection.All(i => i == collection.First()))
? collection.First() : otherValue;.
Oder wenn Sie sich Sorgen machen, First () für jedes Element auszuführen (was ein gültiges Leistungsproblem sein könnte):
var first = collection.First();
return collection.All(i => i == first) ? first : otherValue;
Dies mag spät sein, aber eine Erweiterung, die für Wert- und Referenztypen gleichermaßen funktioniert, basierend auf Erics Antwort:
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;
}
Eine Alternative zur Verwendung von LINQ:
var set = new HashSet<int>(values);
return (1 == set.Count) ? values.First() : otherValue;
Ich habe festgestellt, dass die Verwendung HashSet<T>
für Listen mit bis zu ~ 6.000 Ganzzahlen schneller ist als:
var value1 = items.First();
return values.All(v => v == value1) ? value1: otherValue;
HashSet<T>
anfangs schneller ist als die Verwendung der LINQ-Anweisungen in meiner Antwort. Wenn ich dies jedoch in einer Schleife mache, ist LINQ schneller.
GetHashCode()
, was schwierig korrekt durchzuführen ist. Weitere Informationen finden Sie unter: stackoverflow.com/a/371348/2607840 .
Eine geringfügige Abweichung vom obigen vereinfachten Ansatz.
var result = yyy.Distinct().Count() == yyy.Count();
Wenn ein Array vom Typ Multidimension wie unten ist, müssen wir unter linq schreiben, um die Daten zu überprüfen.
Beispiel: Hier sind die Elemente 0 und ich überprüfe, ob alle Werte 0 sind oder nicht.
ip1 =
0 0 0 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";
}