簡體   English   中英

C#按升序和降序對數組進行排序

[英]C# sorting arrays in ascending and descending order

我在編寫一個方法時遇到問題,如果數組(數字)的元素按升序或降序排序,則返回 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;
}

任何人都能夠提供有關如何檢查已排序的降序數組的幫助? 干杯!

它應該是這樣的:

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

例子:

在此處輸入圖片說明

它看起來更像是一項學術作業,而不是一個實際問題。 我想偶爾回到基礎不會有什么壞處:

public static bool IsSortedAscOrDesc(int[] arr)
{
    int last = arr.Length - 1;
    if (last < 1) return true;

    bool isSortedAsc = true;
    bool isSortedDesc = true;

    int i = 0;
    while (i < last && (isSortedAsc || isSortedDesc)) 
    {
        isSortedAsc &= (arr[i] <= arr[i + 1]);
        isSortedDesc &= (arr[i] >= arr[i + 1]);
        i++;
    }

    return isSortedAsc || isSortedDesc;
}

對具有 2 個(或更少)元素的數組進行排序,
{0,0} 按 asc & desc、{0,1} asc、{1,0} desc、{1,1} asc & desc 排序。
可以使用一個循環,但分離案例似乎更快。 對於超過 2 個元素的數組,
如果第一個元素小於最后一個元素,請檢查:a[i] <= a[i + 1]。
下面我使用“ai <= (ai = a[i])”,將ai的舊值與ai的新值進行比較,每個元素讀取一次。

using System;
class Program
{
    static void Main()
    {
        int i = 512; int[] a = new int[i--]; while (i > 0) a[i] = i--; //a[511] = 1;
        Console.WriteLine(isSorted0(a));
        var w = System.Diagnostics.Stopwatch.StartNew();
        for (i = 1000000; i > 0; i--) isSorted0(a);
        Console.Write(w.ElapsedMilliseconds); Console.Read();
    }

    static bool isSorted0(int[] a)  // 267 ms
    {
        if (a.Length < 3) return true; int j = a.Length - 1;
        return a[0] < a[j] ? incr(a) : a[0] > a[j] ? decr(a) : same(a);
    }
    static bool incr(int[] a)
    {
        int ai = a[0], i = 1, j = a.Length;
        while (i < j && ai <= (ai = a[i])) i++; return i == j;
    }
    static bool decr(int[] a)
    {
        int ai = a[0], i = 1, j = a.Length;
        while (i < j && ai >= (ai = a[i])) i++; return i == j;
    }
    static bool same(int[] a)
    {
        int ai = a[0], i = 1, j = a.Length - 1;
        while (i < j && ai == a[i]) i++; return i == j;
    }

    static bool isSorted1(int[] numbers)  // 912 ms  accepted answer
    {
        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;
    }
}

一個簡短的版本。

    static bool isSorted(int[] a)
    {
        if (a.Length < 3) return true; int i = a.Length - 1, ai = a[i--];
        if (ai > a[0]) while (i >= 0 && ai >= (ai = a[i])) i--;
        else if (ai < a[0]) while (i >= 0 && ai <= (ai = a[i])) i--;
        else while (i >= 0 && ai == a[i]) i--; return i < 0;
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM