我很感兴趣,如果在LINQ中有一种方法来检查列表中的所有数字是否单调递增?
例
List<double> list1 = new List<double>() { 1,2,3,4 }; Debug.Assert(list1.IsIncreasingMonotonically() == true); List<double> list2 = new List<double>() { 1,100,-5 }; Debug.Assert(list2.IsIncreasingMonotonically() == false);
我问的原因是我想知道将列表中的元素与其前一个元素进行比较的技术,这是我在使用LINQ时从未理解过的.
C#中的完成示例类
根据下面@Servy的官方回答,这是我现在使用的完整课程.它为您的项目添加扩展方法,以检查列表是单调增加/减少还是严格单调增加/减少.我正在尝试习惯一种函数式编程风格,这是一种很好的学习方法.
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MyHelper { /// <summary> /// Classes to check if a list is increasing or decreasing monotonically. See: /// https://stackoverflow.com/questions/14815356/is-it-possible-to-use-linq-to-check-if-all-numbers-in-a-list-are-increasing-mono#14815511 /// Note the difference between strictly monotonic and monotonic,see: /// http://en.wikipedia.org/wiki/Monotonic_function /// </summary> public static class IsMonotonic { /// <summary> /// Returns true if the elements in the are increasing monotonically. /// </summary> /// <typeparam name="T">Type of elements in the list.</typeparam> /// <param name="list">List we are interested in.</param> /// <returns>True if all of the the elements in the list are increasing monotonically.</returns> public static bool IsIncreasingMonotonically<T>(this List<T> list) where T : IComparable { return list.Zip(list.Skip(1),(a,b) => a.CompareTo(b) <= 0).All(b => b); } /// <summary> /// Returns true if the elements in the are increasing strictly monotonically. /// </summary> /// <typeparam name="T">Type of elements in the list.</typeparam> /// <param name="list">List we are interested in.</param> /// <returns>True if all of the the elements in the list are increasing monotonically.</returns> public static bool IsIncreasingStrictlyMonotonically<T>(this List<T> list) where T : IComparable { return list.Zip(list.Skip(1),b) => a.CompareTo(b) < 0).All(b => b); } /// <summary> /// Returns true if the elements in the are decreasing monotonically. /// </summary> /// <typeparam name="T">Type of elements in the list.</typeparam> /// <param name="list">List we are interested in.</param> /// <returns>True if all of the the elements in the list are decreasing monotonically.</returns> public static bool IsDecreasingMonotonically<T>(this List<T> list) where T : IComparable { return list.Zip(list.Skip(1),b) => a.CompareTo(b) >= 0).All(b => b); } /// <summary> /// Returns true if the elements in the are decreasing strictly monotonically. /// </summary> /// <typeparam name="T">Type of elements in the list.</typeparam> /// <param name="list">List we are interested in.</param> /// <returns>True if all of the the elements in the list are decreasing strictly monotonically.</returns> public static bool IsDecreasingStrictlyMonotonically<T>(this List<T> list) where T : IComparable { return list.Zip(list.Skip(1),b) => a.CompareTo(b) > 0).All(b => b); } /// <summary> /// Returns true if the elements in the are increasing monotonically. /// </summary> /// <typeparam name="T">Type of elements in the list.</typeparam> /// <param name="list">List we are interested in.</param> /// <returns>True if all of the the elements in the list are increasing monotonically.</returns> public static bool IsIncreasingMonotonicallyBy<T>(this List<T> list,Func<T> x) where T : IComparable { return list.Zip(list.Skip(1),b) => a.CompareTo(b) <= 0).All(b => b); } public static void UnitTest() { { List<double> list = new List<double>() { 1,4 }; Debug.Assert(list.IsIncreasingMonotonically<double>() == true); Debug.Assert(list.IsIncreasingStrictlyMonotonically<double>() == true); Debug.Assert(list.IsDecreasingMonotonically<double>() == false); Debug.Assert(list.IsDecreasingStrictlyMonotonically<double>() == false); } { List<double> list = new List<double>() { 1,-5 }; Debug.Assert(list.IsIncreasingMonotonically() == false); Debug.Assert(list.IsIncreasingStrictlyMonotonically() == false); Debug.Assert(list.IsDecreasingMonotonically() == false); Debug.Assert(list.IsDecreasingStrictlyMonotonically() == false); } { List<double> list = new List<double>() {1,1,4,4}; Debug.Assert(list.IsIncreasingMonotonically() == true); Debug.Assert(list.IsIncreasingStrictlyMonotonically<double>() == false); Debug.Assert(list.IsDecreasingMonotonically() == false); Debug.Assert(list.IsDecreasingStrictlyMonotonically() == false); } { List<double> list = new List<double>() { 4,1 }; Debug.Assert(list.IsIncreasingMonotonically() == false); Debug.Assert(list.IsIncreasingStrictlyMonotonically<double>() == false); Debug.Assert(list.IsDecreasingMonotonically() == true); Debug.Assert(list.IsDecreasingStrictlyMonotonically() == true); } { List<double> list = new List<double>() { 4,1 }; Debug.Assert(list.IsIncreasingMonotonically() == false); Debug.Assert(list.IsIncreasingStrictlyMonotonically<double>() == false); Debug.Assert(list.IsDecreasingMonotonically() == true); Debug.Assert(list.IsDecreasingStrictlyMonotonically() == false); } } } }
解决方法
public static bool IsIncreasingMontonically<T>(List<T> list) where T : IComparable { return list.Zip(list.Skip(1),b) => a.CompareTo(b) <= 0) .All(b => b); }
请注意,这会迭代序列两次.对于List来说,对于IEnumerable或IQueryable来说,这根本不是问题,这可能是坏事,所以在你改变List< T>之前要小心.到IEnumerable< T>.