2010-10-21 11 views
17

Estoy leyendo un libro de C# para principiantes, y en cada extremo del capítulo, hay ejercicios para responder en función de las lecciones abordadas.¿Es posible expresar este código en LINQ?

Uno de esos ejercicios va de esta manera: (no las formulaciones exactas)

escribir un programa que acepte un int como la longitud de la matriz, y los valores de la matriz.
A continuación, se imprimirá:
"" si la matriz no está ordenada de forma ascendente.
"" si está ordenado. Y,
"" si está ordenado, pero hay duplicados.

Ejemplo:

// 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 

No sé si mi lógica aquí es absoluta, pero de alguna manera se está trabajando,
y lo he hecho en mi manera de utilizar este código:

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

¿Es posible expresar esto en LINQ? ¿Cómo?

+3

+1 por hacer una pregunta bien estructurado, así como con ganas de saber cómo mejorar lo que ya has hecho. – RPM1984

+0

@ RPM1984: gracias señor :) – yonan2236

+0

Dado que el código real que contiene la lógica 'isSorted' tiene menos de 10 líneas (y debería ser realmente en su propio método), ¿realmente desea una enreverada declaración LINQ para reemplazarlo? –

Respuesta

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

Gracias señor, voy a probar el suyo ... – yonan2236

+0

Sí, este es el camino a seguir. Buen trabajo. +1 – RPM1984

+0

funciona señor ... :) gracias. – yonan2236

5

Una alternativa LINQ pura ... (por interés académico (pero probablemente aún más rápido que la respuesta aceptada!)

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 ... ¿qué es 'entrada' aquí? ¿Es mi matriz? – yonan2236

+0

Sí, la entrada sería su matriz. –

+0

gracias señor por su versión de respuesta :) – yonan2236

3

Como nota, su lógica no LINQ expresada tiene un defecto .

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

su regla dice que la matriz debe ser clasificado de forma ascendente, pero tienen duplicados con el fin de obtener una potencia de 2. sin embargo, la lógica volverá 2 para { 1, 9, 7, 7 }.

Otra forma de escribir su código podría ser la siguiente. (Esto no está utilizando LINQ, pero esto es demasiado tiempo para publicar como un comentario a su pregunta.)

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

En este método, vamos a temprana regresar tan pronto como tenemos un elemento menor que el elemento anterior . De lo contrario, estableceremos un booleano si encontramos un valor coincidente. Al final del ciclo, sabemos que la matriz se ordena de forma ascendente. Lo único que queda es comprobar si hubo una coincidencia.

+0

Gracias por mencionar mi error. Aprenderé de eso. – yonan2236

+0

Sir solo una pregunta, en su código anterior, ¿qué significa este fragmento de código? 'int? lastItem = null; '. La cosa '"? "Allí ... – yonan2236

+2

@yonan: Es la abreviatura de' Nullable '. C# 2 introdujo el concepto de tipos de valor anulables. Los tipos de valores normales, como 'int', no se pueden establecer como nulos, lo que hace que los desarrolladores que usen valores" mágicos "a menudo signifiquen" sin valor ". (Considere 'string.IndexOf (substring)' devuelve -1 si la subcadena no se encuentra dentro de la cadena.) Con 'Nullable ', ahora tenemos una forma de indicar que algo no tiene ningún valor. En C#, podemos expresar eso con taquigrafía. 'int?' es la abreviatura de 'Nullable 'como' int' es en realidad C# taquigrafía para 'Int32'. –

0

Sin probar.

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; 

también no probado:

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

Por favor perdone mi arte ascii ... en realidad, avíseme si ese bit es confuso - (x => 0 <= x) –

+0

gracias por la respuesta :) – yonan2236

Cuestiones relacionadas