是否可以使用LINQ检查列表中的所有数字是否单调递增?

Con*_*ngo 9 .net c# linq

我很感兴趣,如果在LINQ中有一种方法来检查列表中的所有数字是否单调递增?

List<double> list1 = new List<double>() { 1, 2, 3, 4 };
Debug.Assert(list1.IsIncreasingMonotonically() == true);

List<double> list2 = new List<double>() { 1, 2, 100, -5 };
Debug.Assert(list2.IsIncreasingMonotonically() == false);
Run Code Online (Sandbox Code Playgroud)

我问的原因是我想知道将列表中的元素与其前一个元素进行比较的技术,这是我在使用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:
    /// http://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), (a, 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), (a, 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), (a, 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), (a, b) => a.CompareTo(b) <= 0).All(b => b);
        }

        public static void UnitTest()
        {
            {
                List<double> list = new List<double>() { 1, 2, 3, 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, 2, 100, -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, 2, 2, 3, 3, 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, 3, 2, 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, 4, 3, 3, 2, 2, 1, 1 };
                Debug.Assert(list.IsIncreasingMonotonically() == false);
                Debug.Assert(list.IsIncreasingStrictlyMonotonically<double>() == false);
                Debug.Assert(list.IsDecreasingMonotonically() == true);
                Debug.Assert(list.IsDecreasingStrictlyMonotonically() == false);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Ser*_*rvy 12

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);
}
Run Code Online (Sandbox Code Playgroud)

请注意,这会迭代序列两次.对于List,这不是在所有问题,对于一个IEnumerable或者IQueryable,这可能是坏的,所以一定要小心前,你只需要改变List<T>IEnumerable<T>.


CR4*_*G14 5

你不打算使用列表OrderBy()并将它们与原始列表进行比较吗?如果它们是相同的那么它会给你的答案伪说话:

var increasing = orignalList.OrderBy(m=>m.value1).ToList();
var decreasing = orignalList.OrderByDescending(m=>m.value1).ToList();

var mono = (originalList == increasing || originalList == decreasing)
Run Code Online (Sandbox Code Playgroud)

  • @millimoose是的,你是对的,我不明白单调性,但仍然,以上都行不通.`originalList == increase`只是比较两个引用,并且总是false,因为`originalList`和`increase`是单独的对象.或者``==`这里只是'比较两个列表相互比较'的简写? (3认同)

Mat*_*int 5

这是一个可行的单行:

var isIncreasing = list.OrderBy(x => x).SequenceEqual(list);
Run Code Online (Sandbox Code Playgroud)

或者,如果您追求性能,这里有一个单行代码,它只会遍历列表一次,并在到达不按顺序的元素时立即退出:

var isIncreasing = !list.SkipWhile((x, i) => i == 0 || list[i - 1] <= x).Any();
Run Code Online (Sandbox Code Playgroud)