I\'m interested if there is a way, in LINQ, to check if all numbers in a list are increasing monotonically?
Example
List l
Here is a one-liner that will work:
var isIncreasing = list.OrderBy(x => x).SequenceEqual(list);
Or if you're going for performance, here is a one-liner that will only traverse the list once, and quits as soon as it reaches an element out of sequence:
var isIncreasing = !list.SkipWhile((x, i) => i == 0 || list[i - 1] <= x).Any();
Use a loop! It's short, fast and readable. With the exception of Servy's answer, most the solutions in this thread are unnecessarily slow (sorting takes 'n log n' time) .
// Test whether a sequence is strictly increasing.
public bool IsIncreasing(IEnumerable<double> list)
{
bool initial = true;
double last = Double.MinValue;
foreach(var x in list)
{
if (!initial && x <= last)
return false;
initial = false;
last = x;
}
return true;
}
IsIncreasing(new List<double>{1,2,3})
returns TrueIsIncreasing(new List<double>{1,3,2})
returns Falsepublic static class EnumerableExtensions
{
private static bool CompareAdjacentElements<TSource>(this IEnumerable<TSource> source,
Func<TSource, TSource, bool> comparison)
{
using (var iterator = source.GetEnumerator())
{
if (!iterator.MoveNext())
throw new ArgumentException("The input sequence is empty", "source");
var previous = iterator.Current;
while (iterator.MoveNext())
{
var next = iterator.Current;
if (comparison(previous, next)) return false;
previous = next;
}
return true;
}
}
public static bool IsSorted<TSource>(this IEnumerable<TSource> source)
where TSource : IComparable<TSource>
{
return CompareAdjacentElements(source, (previous, next) => previous.CompareTo(next) > 0);
}
public static bool IsSorted<TSource>(this IEnumerable<TSource> source, Comparison<TSource> comparison)
{
return CompareAdjacentElements(source, (previous, next) => comparison(previous, next) > 0);
}
public static bool IsStrictSorted<TSource>(this IEnumerable<TSource> source)
where TSource : IComparable<TSource>
{
return CompareAdjacentElements(source, (previous, next) => previous.CompareTo(next) >= 0);
}
public static bool IsStrictSorted<TSource>(this IEnumerable<TSource> source, Comparison<TSource> comparison)
{
return CompareAdjacentElements(source, (previous, next) => comparison(previous, next) >= 0);
}
}
By using an Enumerable.Aggregate method:
list1.Aggregate((a, i) => a > i ? double.MaxValue : i) != double.MaxValue;
public static bool IsIncreasingMontonically<T>(List<T> list)
where T : IComparable
{
return list.Zip(list.Skip(1), (a, b) => a.CompareTo(b) <= 0)
.All(b => b);
}
Note that this iterates the sequence twice. For a List
, that's not a problem at all, for an IEnumerable
or IQueryable
, that could be bad, so be careful before you just change List<T>
to IEnumerable<T>
.
Would you not order the list using OrderBy()
and compare them against the original? If they are the same then it will give your your answer pseudo speaking:
var increasing = orignalList.OrderBy(m=>m.value1).ToList();
var decreasing = orignalList.OrderByDescending(m=>m.value1).ToList();
var mono = (originalList == increasing || originalList == decreasing)