Linq表达式,用于验证列表是按升序还是降序排序

时间:2014-05-09 10:20:40

标签: c# linq

我有一个IEnumerable<DateTime> var,如果它按升序或降序排序,我需要验证。

我可以使用for循环来做到这一点,但有没有办法使用LINQ表达式?

5 个答案:

答案 0 :(得分:8)

var orderedByAsc = input.OrderBy(d => d);
if (input.SequenceEqual(orderedByAsc))
{
    Console.WriteLine("Ordered by Asc");
    return;
}

var orderedByDsc = input.OrderByDescending(d => d);
if (input.SequenceEqual(orderedByDsc))
{
    Console.WriteLine("Ordered by Dsc");
    return;
}

Console.WriteLine("not sorted");

答案 1 :(得分:6)

升序:

myEnumerable.Zip(myEnumerable.Skip(1), (curr, next) => curr <= next).All(x => x);

降序:

myEnumerable.Zip(myEnumerable.Skip(1), (curr, next) => curr >= next).All(x => x);

但是使用循环,LINQ不是一切的神奇解决方案。

答案 2 :(得分:2)

如果您确定该列表是有序的,那么您可以简单地比较列表的第一个和最后一个元素,看它是按升序还是降序。

答案 3 :(得分:0)

这可能是过度设计但有希望教育和一些用途!

public enum SortedState
{
    NoValues,
    Undecided,
    Ascending,
    Descending,
    Mixture
};

public class AscOrDescHelper<T> where T : IComparable<T>
{
    SortedState state;
    T lastValue;
    bool uniqueValues;

    public AscOrDescHelper()
    {
        state = SortedState.NoValues;
        uniqueValues = true;    // tentative assumption
    }

    public AscOrDescHelper<T> ProcessNextValue(T next)
    {
        switch (state)
        {
            case SortedState.NoValues:
                state = SortedState.Undecided;
                break;
            case SortedState.Undecided:
            case SortedState.Ascending:
            case SortedState.Descending:
                int cmp = next.CompareTo(lastValue);
                switch (state)
                {
                    case SortedState.Undecided:
                        if (cmp > 0)
                        {
                            state = SortedState.Ascending;
                        }
                        else if (cmp < 0)
                        {
                            state = SortedState.Descending;
                        }
                        else
                        {
                            uniqueValues = false;
                        }
                        break;
                    case SortedState.Ascending:
                        if (cmp < 0)
                        {
                            state = SortedState.Mixture;
                        }
                        else if (cmp == 0)
                        {
                            // Not unique
                            uniqueValues = false;
                        }
                        break;
                    case SortedState.Descending:
                        if (cmp > 0)
                        {
                            state = SortedState.Mixture;
                        }
                        else if (cmp == 0)
                        {
                            // Not unique
                            uniqueValues = false;
                        }
                        break;
                }
                break;
        }

        lastValue = next;

        return this;
    }

    public SortedState State()
    {
        return state;
    }

    public bool? Unique()
    {
        return state == SortedState.Mixture ? (bool?)null : uniqueValues;
    }

    public override string ToString()
    {
        return string.Format(
            "{0} ({1})",
            State(),
            Unique().HasValue ? (Unique().Value ? "unique" : "not unique")
                : "unknown uniqueness");
    }
};

static void CheckIfSorted<T>(IEnumerable<T> values) where T : IComparable<T>
{
    Console.WriteLine(
        values.Aggregate(
            new AscOrDescHelper<T>(),
            (last, next) => last.ProcessNextValue(next)));
}

static void Main()
{
    CheckIfSorted(new string[]{ "amy", "kate", "sally" });
    CheckIfSorted(new int[]{ 7, 5, 5 });
    CheckIfSorted(new int[]{ 2, 3, 1 });
    // Gives:
    //   Ascending (unique)
    //   Descending (not unique)
    //   Mixture (unknown uniqueness)
}

我是C#初学者,所以欢迎建设性的建议;)

答案 4 :(得分:0)

LINQ扩展。 MoreLinq图书馆的优秀候选人:

public static bool IsOrdered<T>(this IEnumerable<T> source, IComparer<T> comparer = null)
{
    return source.IsOrdered(OrderByDirection.Ascending, comparer);
}

public static bool IsOrdered<T>(this IEnumerable<T> source, OrderByDirection direction, IComparer<T> comparer = null)
{
    if (source == null)
    {
        throw new ArgumentNullException(nameof(source));
    }

    if (comparer == null)
    {
        comparer = Comparer<T>.Default;
    }

    int d = direction == OrderByDirection.Ascending ? 1 : -1;

    Func<T, T, int> compareFunc= (i1, i2) => d * comparer.Compare(i1, i2);
    return IsOrderedImpl(source, compareFunc);
}

public static bool IsOrdered<T>(this IEnumerable<T> source, Func<T, T, int> compareFunc)
{
    if (source == null)
    {
        throw new ArgumentNullException(nameof(source));
    }
    if (compareFunc == null)
    {
        throw new ArgumentNullException(nameof(compareFunc));
    }

    return IsOrderedImpl(source, compareFunc);
}

private static bool IsOrderedImpl<T>(this IEnumerable<T> source, Func<T, T, int> compareFunc)
{
    T prevItem = default(T);
    int i = 0;
    foreach (T item in source)
    {
        if (i == 0)
        {
            prevItem = item;
        }
        else
        {
            if (compareFunc(prevItem, item) > 0)
            {
                return false;
            }

            prevItem = item;
        }

        ++i;
    }

    return true;
}

[TestMethod]
public void TestIsOrdered01()
{
    Assert.IsTrue(Enumerable.Range(1, 10).IsOrdered());
    Assert.IsFalse(Enumerable.Range(1, 10).Reverse().IsOrdered());
    Assert.IsTrue(Enumerable.Range(1, 10).IsOrdered(OrderByDirection.Ascending));
    Assert.IsFalse(Enumerable.Range(1, 10).IsOrdered(OrderByDirection.Descending));
    Assert.IsFalse(Enumerable.Range(1, 10).Reverse().IsOrdered(OrderByDirection.Ascending));
    Assert.IsTrue(Enumerable.Range(1, 10).Reverse().IsOrdered(OrderByDirection.Descending));
}