I'm having trouble writing a method that returns true if the elements of an array (numbers) are in sorted order, ascending or descending, and false, if they are not in any sorted order. I can return a correct boolean value if the array is ascending but i do not know how to check for descending order as well in the same method. I currently have:
public static bool IsArraySorted(int[] numbers)
{
for (int i = 1; i < numbers.Length; i++)
{
if (numbers[i - 1] > numbers[i])
return false;
}
return true;
}
Anyone able to offer help on how to check for a sorted descending array as well? Cheers!
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();
public static boolean checkSortedness(final int[] data)
{
for (int i = 1; i < data.length; i++)
{
if (data[i-1] > data[i]) {
return false;
}
}
return true;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With