Native C # support for checking IEnumerable sorting?

Is there LINQ support for checking IEnumerable<T> collation? I have an enumerable that I want to check, sorted in non-decreasing order, but I cannot find the built-in support for it in C #.

I wrote my own extension method using IComparables<T> :

 public static bool IsSorted<T>(this IEnumerable<T> collection) where T : IComparable<T> { Contract.Requires(collection != null); using (var enumerator = collection.GetEnumerator()) { if (enumerator.MoveNext()) { var previous = enumerator.Current; while (enumerator.MoveNext()) { var current = enumerator.Current; if (previous.CompareTo(current) > 0) return false; previous = current; } } } return true; } 

And one using the IComparer<T> object:

 public static bool IsSorted<T>(this IEnumerable<T> collection, IComparer<T> comparer) { Contract.Requires(collection != null); using (var enumerator = collection.GetEnumerator()) { if (enumerator.MoveNext()) { var previous = enumerator.Current; while (enumerator.MoveNext()) { var current = enumerator.Current; if (comparer.Compare(previous, current) > 0) return false; previous = current; } } } return true; } 
+4
source share
4 answers

You can check if the collection is IOrderedEnumerable , but this will only work if the ordering is the last operation that was applied to the sequence. So basically you need to check the whole sequence manually.

Also keep in mind that if a sequence is IOrderedEnumerable , you really cannot tell which condition was used to sort the sequence.


Here is a general method that you can use to check if a sequence is sorted in ascending order by the field you want to check:

 public static bool IsOrdered<T, TKey>( this IEnumerable<T> source, Func<T, TKey> keySelector) { if (source == null) throw new ArgumentNullException("source"); var comparer = Comparer<TKey>.Default; using (var iterator = source.GetEnumerator()) { if (!iterator.MoveNext()) return true; TKey current = keySelector(iterator.Current); while (iterator.MoveNext()) { TKey next = keySelector(iterator.Current); if (comparer.Compare(current, next) > 0) return false; current = next; } } return true; } 

Using:

 string[] source = { "a", "ab", "c" }; bool isOrdered = source.IsOrdered(s => s.Length); 

You can create a similar IsOrderedDescending method - just change the result of the comparison check to comparer.Compare(current, next) < 0 .

+5
source

There is no such built-in support.

Obviously, if your IEnumerable<T> also implements IOrderedEnumerable<T> , you do not need to do additional checking, otherwise you will have to implement an extension method like you.

You might want to add a direction parameter or change its name to IsSortedAscending<T> . In addition, your T may have different properties for sorting, so it should be obvious to you what โ€œsortedโ€ means.

+1
source

I often find using the extension method I created called SelectPairs() , and also in this case:

 /// <summary> /// Projects two consecutive pair of items into tuples. /// {1,2,3,4} -> {(1,2), (2,3), (3,4)) /// </summary> public static IEnumerable<Tuple<T, T>> SelectPairs<T>(this IEnumerable<T> source) { return SelectPairs(source, (t1, t2) => new Tuple<T, T>(t1, t2)); } /// <summary> /// Projects two consecutive pair of items into a new form. /// {1,2,3,4} -> {pairCreator(1,2), pairCreator(2,3), pairCreator(3,4)) /// </summary> public static IEnumerable<TResult> SelectPairs<T, TResult>( this IEnumerable<T> source, Func<T, T, TResult> pairCreator) { T lastItem = default(T); bool isFirst = true; foreach (T currentItem in source) { if (!isFirst) { yield return pairCreator(lastItem, currentItem); } isFirst = false; lastItem = currentItem; } } 

Use it as follows:

 bool isOrdered = myCollection .SelectPairs() .All(t => t.Item1.MyProperty < t.Item2.MyProperty); 

This operator, of course, can be placed in another extension method:

 public static bool IsOrdered<T>( this IEnumerable<T> source, Func<T, T, int> comparer) { return source.SelectPairs().All(t => comparer(t.Item1, t.Item2) > 0); } bool isOrdered = myCollection .IsOrdered((o1, o2) => o2.MyProperty - o1.MyProperty); 
0
source

There is a small and simple version using Zip, although your IEnumerable is really twice listed.

var source = Enumerable.Range (1,100000);

bool isSorted = source.Zip (source.Skip (1), (a, b) => b> = a) .All (x => x);

0
source

Source: https://habr.com/ru/post/989302/


All Articles