How to check if a IEnumerable is sorted?

2019-09-22 05:01发布

问题:

How to check if a IEnumerable is sorted?

bool IsSorted<T>(IEnumerable<T> enumerable)
{
   ???
}

回答1:

One example of such method could be:

static bool IsSorted<T>(IEnumerable<T> enumerable) where T : IComparable<T> {
    T prev = default(T);
    bool prevSet = false;
    foreach (var item in enumerable) {
        if (prevSet && (prev == null || prev.CompareTo(item) > 0))
            return false;
        prev = item;
        prevSet = true;
    }
    return true;
}

Works with most built-in types like numbers or strings, because they implement IComparable.



回答2:

Just check that every item is not less then prior one:

  public static partial class EnumerableExtensions {
    public static bool IsSorted<T>(this IEnumerable<T> source, 
                                   IComparer<T> comparer = null) {
      if (null == source)
        throw new ArgumentNullException("source");

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

      if (null == comparer)
        throw new ArgumentException("No default comparer found.");

      T prior = default(T);
      bool first = true;

      foreach (var item in source) {
        if (!first && comparer.Compare(prior, item) > 0)
          return false;

        first = false;
        prior = item; 
      }

      return true;
    }
  }


回答3:

This checks for Ascending or Descending sort rather than just ascending

   enum SortOrder
    {
        Unknown = 0,
        Ascending = 1,
        Descending = 2
    }

    static bool IsSorted<T>(IEnumerable<T> enumerable)
    {
        var enumerator = enumerable.GetEnumerator();
        // Empty Enumerable
        if (!enumerator.MoveNext())
            return true;
        SortOrder order = SortOrder.None;

        // First Item
        var last = enumerator.Current;
        while(enumerator.MoveNext())
        { 
            var result = Comparer<T>.Default.Compare(last, enumerator.Current);

            switch (order)
            {
                case SortOrder.Unknown:

                    if (result == 0)
                        break;
                    if(result == -1)
                        order = SortOrder.Ascending;
                    else 
                        order = SortOrder.Descending;

                    break;
                case SortOrder.Descending:
                    if (result == -1)
                        return false;
                    break;
                case SortOrder.Ascending:
                    if (result == 1)
                        return false;
                    break;
            }
            last = enumerator.Current;

        }


        return true;
    }