2010-10-21 13 views
17

Czytam książkę C# dla początkujących, a na każdym końcu rozdziału znajdują się ćwiczenia, na które należy odpowiedzieć w oparciu o lekcje.Czy można wyrazić ten kod w LINQ?

Jeden z tych ćwiczeń idzie w ten sposób: (nie dokładne sformułowania)

napisać program, który będzie akceptować int ponieważ długość tablicy i wartości dla tablicy.
Następnie zostanie wydrukowane:
"" jeśli tablica nie jest posortowana w porządku rosnącym.
"" jeśli jest posortowany. I,
"" jeśli jest posortowany, ale są duplikaty.

Przykład:

// Sorted 
Input: 1, 2, 3, 5 
Print: 1 

// Not sorted 
Input: 2, 1, 3, 6 
Print: 0 

// Sorted, but with duplicates 
Input: 2, 2, 3, 7 
Print: 2 

Nie wiem, czy moja logika tutaj jest absolutna, ale jakoś to działa,
i zrobiłam go w drodze przy użyciu tego kodu:

int arrayLength = 0; 
int prev, next; 
int sortStatus = 1; 

Console.Write("Input array Length: "); 
arrayLength = Convert.ToInt32(Console.ReadLine()); 
int[] ar = new int[arrayLength]; 

for (int x = 0; x < arrayLength; x++) 
{ 
    Console.Write("Input {0} value: ", (x+1).ToString()); 
    ar[x] = Convert.ToInt32(Console.ReadLine()); 
} 

for (int x = 0; x < ar.Length-1; x++) 
{ 
    prev = (int)ar[x]; 
    next = (int)ar[x + 1]; 

    if (next < prev) 
     sortStatus = 0; 
    if (next == prev) 
     sortStatus = 2; 
} 

Console.Write(sortStatus.ToString()); 
Console.Read(); 

Czy można wyrazić to w LINQ? W jaki sposób?

+3

+1 dla zadaje pytanie dobrze zorganizowanego, a także chcą wiedzieć, jak poprawić to, co zostało już zrobione. – RPM1984

+0

@ RPM1984: dziękuję, proszę pana :) – yonan2236

+0

Biorąc pod uwagę fakt, że rzeczywisty kod zawierający logikę "isSorted" ma mniej niż 10 linii (i naprawdę powinien być w swojej własnej metodzie), czy naprawdę chcesz, aby zastąpiła go zawiłe polecenie LINQ? –

Odpowiedz

17
if (ar.SequenceEqual(ar.OrderBy(x => x))) 
{ 
    if (ar.Distinct().Count() == ar.Length) 
     return 1; 
    else 
     return 2; 
} 
else 
{ 
    return 0; 
} 
+0

Dzięki, sir, spróbuję twojego ... – yonan2236

+0

Tak, to jest droga. Dobra robota. +1 – RPM1984

+0

to działa, proszę pana ... :) dzięki. – yonan2236

5

Czysty LINQ alternatywa ... (tylko dla zainteresowań naukowych (ale chyba jeszcze szybciej niż przyjętym odpowiedź!)

var input = new int[] { 1, 2, 3, 4, 5 }; 

var output = input.Zip(input.Skip(1), (a, b) => new {a=a, b=b}) 
       .Aggregate(1, (status, x) => status == 0 ? 0 : ((x.a > x.b ? 0 : (x.a == x.b ? 2 : status)))); 
+0

Hmm .. co to jest "wejście" tutaj? Czy to moja tablica? – yonan2236

+0

Tak, wejście będzie twoją tablicą. –

+0

dziękuję za twoją wersję odpowiedzi :) – yonan2236

3

Jako notatkę, twoja logika zakaz wyrażony LINQ ma wadę .

if (next < prev) 
    sortStatus = 0; 
if (next == prev) 
    sortStatus = 2; 

reguła mówi, że tablica musi być sortowane rosnąco ale mają duplikaty w celu uzyskania wyjścia 2. Jednakże logika powróci 2 dla { 1, 9, 7, 7 }.

Innym sposobem napisania kodu może być: (To nie jest przy użyciu LINQ, ale to jest zbyt długo, aby pisać w komentarzu do Twojego pytania.)

static int EvaluateArray(int[] array) 
{ 
    int? lastItem = null; 
    bool match = false; 
    foreach (int item in array) 
    { 
     if (item < lastItem) 
      return 0; 
     else if (item == lastItem) 
      match = true; 

     lastItem = item; 
    } 

    if (match) 
     return 2; 

    return 1; 
} 

W tej metodzie, będziemy wcześnie wrócić tak szybko, jak mamy element mniej niż w poprzednim punkcie . W przeciwnym razie ustawimy wartość boolowską, jeśli natkniemy się na pasującą wartość. Na końcu pętli wiemy, że tablica jest posortowana rosnąco. Pozostaje tylko sprawdzenie, czy był mecz.

+0

Dziękuję za przypomnienie mojego błędu. Będę się z tego uczyć. – yonan2236

+0

Proszę odpowiedzieć sobie w powyższym kodzie na pytanie, co oznacza ten fragment kodu? 'int? lastItem = null; '. Rzecz "tam" ... – yonan2236

+2

@yonan: To jest skrót od 'Nullable '. C# 2 wprowadził pojęcie typów wartości zerowych. Normalnych typów wartości, takich jak 'int', nie można ustawić na null, co spowodowało, że programiści używający" magicznych "wartości często oznaczają" brak wartości ". (Weź pod uwagę 'string.IndexOf (substring)' zwraca -1, jeśli podłańcuch nie znajduje się w ciągu znaków.) Przy 'Nullable ' mamy teraz sposób, aby wskazać, że coś nie ma wartości. W języku C# możemy wyrazić to skrótem. 'int?' jest skrótem dla 'Nullable ' podobnie jak 'int' jest skrótem C# dla' Int32'. –

0

Nienormowany.

IEnumerable<int> signs = 
    from i in Enumerable.Range(0, ar.Length).Skip(1) 
    select ar[i-1].CompareTo(ar[i]); 

int result = 
    signs.Any(sign => sign < 0) ? 0 : 
    signs.All(sign => 0 < sign) ? 1 : 
    2; 

również niesprawdzone:

int minSign = !ar.Skip(1).Any() ? 1 : 
(
    from i in Enumerable.Range(0, ar.Length).Skip(1) 
    select ar[i-1].CompareTo(ar[i]) 
).TakeWhile(x => 0 <= x).Min(); 

int result = 
    minSign < 0 ? 0 : 
    0 < minSign ? 1 : 
    2; 
+0

Proszę wybaczyć moją sztukę ascii ... właściwie, daj mi znać, jeśli ten kawałek jest mylący - (x => 0 <= x) –

+0

dzięki za odpowiedź :) – yonan2236