C# sorting arrays in ascending and descending order
It should be something like:
public static bool IsArraySorted(int[] numbers)
{
bool? ascending = null;
for (int i = 1; i < numbers.Length; i++)
{
if (numbers[i - 1] != numbers[i])
{
bool ascending2 = numbers[i - 1] < numbers[i];
if (ascending == null)
{
ascending = ascending2;
}
else if (ascending.Value != ascending2)
{
return false;
}
}
}
return true;
}
Note the use of the ascending
variable to save the "direction" of the array. It is initialized the first time two elements that are different are found.
Note that if you want, you can even return the "direction" of the array:
public static bool IsArraySorted(int[] numbers, out bool isAscending)
{
isAscending = true;
bool? ascending = null;
and inside the if (ascending == null)
if (ascending == null)
{
ascending = ascending2;
isAscending = ascending2;
}
This is a generic version based on IEnumerable<TSource>
:
public static bool IsSorted<TSource>(IEnumerable<TSource> source, out bool isAscending, Comparer<TSource> comparer = null)
{
isAscending = true;
if (comparer == null)
{
comparer = Comparer<TSource>.Default;
}
bool first = true;
TSource previous = default(TSource);
bool? ascending = null;
foreach (TSource current in source)
{
if (!first)
{
int cmp = comparer.Compare(previous, current);
if (cmp != 0)
{
bool ascending2 = cmp < 0;
if (ascending == null)
{
ascending = ascending2;
isAscending = ascending2;
}
else if (ascending.Value != ascending2)
{
return false;
}
}
}
first = false;
previous = current;
}
return true;
}
Note the use of bool first
/TSource previous
to handle the i - 1
(and the fact that the for
cycle was able to "skip" the first element)
Using Linq -
public static bool IsArraySorted(int[] numbers)
{
var orderedAsc = numbers.OrderBy(a => a);
var orderedDes = numbers.OrderByDescending(a => a);
bool isSorted = numbers.SequenceEqual(orderedAsc) ||
numbers.SequenceEqual(orderedDes);
return isSorted;
}
This uses one loop to test both cases:
public static bool IsSorted<T>(IEnumerable<T> items, Comparer<T> comparer = null)
{
if (items == null) throw new ArgumentNullException("items");
if (!items.Skip(1).Any()) return true; // only one item
if (comparer == null) comparer = Comparer<T>.Default;
bool ascendingOrder = true; bool descendingOrder = true;
T last = items.First();
foreach (T current in items.Skip(1))
{
int diff = comparer.Compare(last, current);
if (diff > 0)
{
ascendingOrder = false;
}
if (diff < 0)
{
descendingOrder = false;
}
last = current;
if(!ascendingOrder && !descendingOrder) return false;
}
return (ascendingOrder || descendingOrder);
}
usage:
int[] ints = { 1, 2, 3, 4, 5, 6 };
bool isOrderedAsc = IsSorted(ints); // true
bool isOrderedDesc = IsSorted(ints.Reverse()); //true
If you make it an extension method you can use it with any type:
bool ordered = new[]{"A", "B", "C"}.IsSorted();