I have a List(Of DateTime) items. How can I check if all the items are the same with a LINQ query? At any given time there could be 1, 2, 20, 50 or 100 items in the list.
Asked
Active
Viewed 9.3k times
5 Answers
151
Like this:
if (list.Distinct().Skip(1).Any())
Or
if (list.Any(o => o != list[0]))
(which is probably faster)

SLaks
- 868,454
- 176
- 1,908
- 1,964
-
28Potentially easier to read with "All" instead of "Any". You may also want to use First() instead of [0] in case list access cannot be performed (IEnumerable). if (list.All(o => o == list.First())) { ... } – Graeme Wicksted Sep 08 '14 at 21:00
-
4`list.Distinct().Skip(1).Any()` is no different than `list.Distinct().Count != 1` right? – Simon_Weaver Sep 17 '16 at 19:15
-
1@GraemeWicksted the whole point of Any() is to be faster if one item is found that DOESN'T match. Then you stop evaluating the list. What IS slightly clearer though is `!(list.Any(o => o != list[0]))` which is true if there are no items that are different from the first one - i.e. if they're all the same – Simon_Weaver Sep 17 '16 at 19:21
-
10@Simon_Weaver `Any()` is used to find at least 1 match while `All()` is used to ensure all items match. In either case, if a non-match is encountered in All or a match is found in Any, they will halt iteration. So `!(list.Any(o => o != list[0]));` and `list.All(o => o == list[0]);` will always have the same iteration count. Thus both will have about the same execution time. P.S. You are correct, in that `list.Distinct().Skip(1).Any()` is analogous to `list.Distinct().Count != 1` just be aware Count can be slower than Any (possibly even in this case) with > 1 element. – Graeme Wicksted Sep 19 '16 at 00:57
-
But count has to iterate over the entire distinct list. If you have more than 2 sets, it's slower. – Lee Louviere Sep 16 '19 at 15:53
17
I created simple extension method mainly for readability that works on any IEnumerable.
if (items.AreAllSame()) ...
And the method implementation:
/// <summary>
/// Checks whether all items in the enumerable are same (Uses <see cref="object.Equals(object)" /> to check for equality)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="enumerable">The enumerable.</param>
/// <returns>
/// Returns true if there is 0 or 1 item in the enumerable or if all items in the enumerable are same (equal to
/// each other) otherwise false.
/// </returns>
public static bool AreAllSame<T>(this IEnumerable<T> enumerable)
{
if (enumerable == null) throw new ArgumentNullException(nameof(enumerable));
using (var enumerator = enumerable.GetEnumerator())
{
var toCompare = default(T);
if (enumerator.MoveNext())
{
toCompare = enumerator.Current;
}
while (enumerator.MoveNext())
{
if (toCompare != null && !toCompare.Equals(enumerator.Current))
{
return false;
}
}
}
return true;
}

MSkuta
- 1,630
- 13
- 19
-
1Nice! Just wondering about the empty list implementation. I'm not sure if I would assume that an empty list means "all are the same" - feels like a case for the consumer to handle, so I think I'm going to throw if the list empty. "Are the apples the same? No clue, because there are no apples in the basket" – Dirk Boer Oct 18 '19 at 07:54
-
This extension does not work in cases where the IEnumerable contains null values. For this case I added `if (toCompare == null && enumerator.Current != null) { return false; }` – MatterOfFact Mar 12 '23 at 08:29
14
My variant:
var numUniques = 1;
var result = list.Distinct().Count() == numUniques;

Seva
- 1,631
- 2
- 18
- 23
-
2I like this, it's very readable and shows intent compared to the skip1/any solution. – tkit Nov 29 '19 at 11:51
9
This is an option, too:
if (list.TrueForAll(i => i.Equals(list.FirstOrDefault())))
It is faster than if (list.Distinct().Skip(1).Any())
, and performs similarly as
if (list.Any(o => o != list[0]))
, however, the difference is not significant, so I suggest using the more readable one.

KungFury
- 91
- 1
- 3
4
VB.NET version:
If list.Distinct().Skip(1).Any() Then
Or
If list.Any(Function(d) d <> list(0)) Then

jor
- 2,058
- 2
- 26
- 46