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);
私が尋ねる理由は、リスト内の要素を前の要素と比較する手法を知りたいということです。これは、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);
}
}
}
}