2015-06-15 37 views
8

Mam problem z zapisaniem metody, która zwraca wartość true, jeśli elementy tablicy (liczby) są posortowane, rosnące lub malejące, i fałsz, jeśli nie są posortowane zamówienie. Mogę zwrócić poprawną wartość boolowską, jeśli tablica jest rosnąca, ale nie wiem, jak sprawdzić w porządku malejącym, również w tej samej metodzie. Obecnie mam:C# sortowanie tablic w porządku rosnącym i malejącym

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

     } 

     return true; 
    } 

Czy ktoś może zaoferować pomoc w zakresie sprawdzania uporządkowanego układu zstępującego? Twoje zdrowie!

+0

Jeśli istnieją dwa continguus wartości z tym samym numerem co jest pożądane zachowanie? –

+0

Korzystanie z funkcji powrotu kończy działanie, podczas gdy prawdopodobnie chcesz zapętlić całą kolekcję przed zwróceniem czegokolwiek ... –

+0

@Bartdude Myślę, że jest to zgodne z projektem - jeśli już odkryłeś, że nie jest posortowane, nie musisz sprawdzać reszty tablicy :-) –

Odpowiedz

9

To powinno być coś takiego:

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

Zauważ użycie zmiennej ascending zapisać "kierunek" tablicy. Został zainicjowany po raz pierwszy, gdy znaleziono dwa różne elementy.

Pamiętaj, że jeśli chcesz, możesz nawet zwrotu „kierunek” tablicy:

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

i wewnątrz if (ascending == null)

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

Jest to ogólny wersja na podstawie 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; 
} 

Uwaga na użycie bool first/obsłużyć i - 1 (i fakt, że cykl for w stanie „przeskok” pierwszego elementu)

+0

Czy mogę użyć tylko (numbers.Length/2) zamiast przechodzenia przez pełną listę? – Amit

+2

@Amit ???? '{1, 2, 3, -5}' Jak byś złapał out-of-order '-5', jeśli nie zaznaczysz ostatniej wartości? – xanatos

+0

@xanatos, Dostaniesz 'OutOfRangeException", jeśli tablica przekazana ma długość 0 lub 1. Będziesz potrzebował sprawdzenia argumentów na górze metody. –

1
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; 
} 
+0

to sprawdza tylko rosnącą posortowaną listę, ale kończy się niepowodzeniem na malejącej posortowanej liście – fubo

+0

'final' to Java, a nie C# – xanatos

3

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

ten wykorzystuje jedną pętlę badanie obu przypadkach:

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

wykorzystanie:

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

Jeśli mak e to metoda rozszerzenia, której można używać z dowolnym typem:

bool ordered = new[]{"A", "B", "C"}.IsSorted(); 
+1

Myślę, że to jest obrzydliwość * bardzo źle źle * wyliczyć dwa razy "IEnumerable <>" ... ('First' /' Skip') – xanatos

+0

@xanatos: Dlaczego? Nie liczę tego dwa razy. Jeśli jest to kolekcja, bierze pierwszy przedmiot, natomiast 'Skip (1)' jest wyliczeniem, które pomija pierwszą. Czym jest obrzydliwość? –

+1

Spróbuj zrobić to do 'IQueryable <>' ... Zapytanie jest rozwiązywane dwa razy (technicznie dwa różne zapytania są wykonywane ... jeden ma "TOP 1" i inny, który emuluje 'Skip (1)') – xanatos

1

Gdzie jest moja odpowiedź? Napisałem go około godziny temu:

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

Przykład:

enter image description here

Powiązane problemy