В C# сортировка массива по возрастанию и убыванию

У меня возникли проблемы с написанием метода, который возвращает true, если элементы массива (числа) находятся в отсортированном порядке, по возрастанию или убыванию, и false, если они не находятся в любом отсортированном порядке. Я могу вернуть правильное логическое значение, если массив по возрастанию, но я не знаю, как проверить порядок убывания в том же методе. В настоящее время у меня:

public static bool IsArraySorted(int[] numbers)
{
    for (int i = 1; i < numbers.Length; i++)
    {
        if (numbers[i - 1] > numbers[i])
            return false;
    }

    return true;
}

кто-нибудь может предложить помощь о том, как проверить сортированный нисходящий массив? Ура!

5 ответов


это должно быть что-то вроде:

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;
}

обратите внимание на использование ascending переменная для сохранения" направления " массива. Он инициализируется при первом обнаружении двух различных элементов.

обратите внимание, что если вы хотите, вы даже можете вернуть "направление" массива:

public static bool IsArraySorted(int[] numbers, out bool isAscending)
{
    isAscending = true;
    bool? ascending = null;

и внутри if (ascending == null)

if (ascending == null)
{
    ascending = ascending2;
    isAscending = ascending2;
}

это общая версия, основанная на 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;
}

обратите внимание на использование bool first/TSource previous обработки i - 1 (и тот факт, что for цикл смог "пропустить" первый элемент)


Использование 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;
}

Это использует один цикл для тестирования обоих случаев:

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);
}

использование:

int[] ints = { 1, 2, 3, 4, 5, 6 };
bool isOrderedAsc = IsSorted(ints); // true
bool isOrderedDesc = IsSorted(ints.Reverse()); //true

Если вы сделаете его методом расширения, вы можете использовать его с любым типом:

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;
}

где мой ответ? Я написал его около часа назад:

public enum SortType
{
     unsorted   = 0,
     ascending  = 1,
     descending = 2
}

public static SortType IsArraySorted(int[] numbers)
{
    bool ascSorted = true;
    bool descSorted = true;

    List<int> asc = new List<int>(numbers);            

    asc.Sort();

    for (int i = 0; i < asc.Count; i++)
    {
        if (numbers[i] != asc[i]) ascSorted = false;
        if (numbers[asc.Count - 1 - i] != asc[i]) descSorted = false;
    }

    return ascSorted ? SortType.ascending : (descSorted? SortType.descending : SortType.unsorted);
}

пример:

enter image description here