2009-09-11 10 views
11

Tengo un código que me gustaría convertir en una expresión linq (preferiblemente con lambdas) para que sea más fácil usarlo como delegado. El código se ve así:Expresión de Linq para establecer todos los valores de una matriz en un valor dado

List<DateTime[]> changes = new List<DateTime[]>(); 
changes = PopulateChanges(); 
for (int i = 0; i < changes.Count; i++) 
{ 
    for(int j = 0; j < changes[i].Length; j++) 
    { 
     changes[i][j] = DateTime.MinValue; 
    } 
} 

Por la vida de mí, parece que no puedo entender esto. He intentado usar ForEach y varias formas de seleccionar, etc. nada parece funcionar bien.

FYI, sé que DateTime está predeterminado en MinValue, en realidad esto está limpiando los arrays a los valores predeterminados una vez que ya se han establecido.

¿Alguien me puede ayudar con una expresión de trabajo?

EDIT:

Creo que lo que realmente estoy diciendo aquí es que quiero una manera concisa para establecer todos los elementos de una matriz multi-dimensional para un valor dado. Ciertamente, el bucle anidado funciona, y ciertamente puedo colocarlo en una función (que ya he hecho). Solo quiero algo más conciso que se pueda usar más fácilmente en un delegado sin crear un monstruo de múltiples líneas.

Respuesta

14

Esto debería hacer el truco.

No es LINQ, y no es muy diferente a los bucles anidados for, apenas un poco menos detallado.

changes.ForEach(x => Array.Clear(x, 0, x.Length)); 

sin duda hay formas de (ab) uso de LINQ para lograr los mismos resultados, pero me gustaría consideran que son cortes sucios. Además, el equivalente LINQ probablemente no sería menos detallado que mi ejemplo anterior.

+0

Me gusta esto. Lo suficientemente cerca para mí, creo. –

2

LINQ no está destinado a ser utilizado para actualizar colecciones. Se trata de realizar consultas, es decir, crear enumerables sobre colecciones existentes. Creo que su código es perfectamente legible y no mejorará mucho si lo fuerza a tener muchas lambdas y cosas por el estilo.

Si desea crear un nuevo List<DateTime[]> con cada elemento se establece en un valor, usted puede hacer esto:

var changes = Enumerable.Range(0, width) 
         .Select(x => Enumerable.Range(0, height) 
               .Select(y => DateTime.MinValue) 
               .ToArray()) 
         .ToList(); 

Si realmente quiere hacerlo usando ForEach/LINQ, es posible abusar Select (pero yo no lo recomiendo):

changes.ForEach(array => array.Select((dt, i) => array[i] = DateTime.Now) 
           .LastOrDefault()); 
+0

Realmente no entiendo por qué dices que no es para esto. Piense en una consulta típica de Linq2SQL donde consulta datos y luego actualiza los valores. ¿Cómo es esto diferente? –

+3

Con LINQ2SQL consulta la base de datos y luego modifica los objetos devueltos. Si desea modificar todos los objetos devueltos, aún debe usar un bucle para iterar sobre los objetos. Y el enumerable que contiene los objetos no se modifica en absoluto. LINQ se trata de realizar consultas, no de actualizar colecciones. – dtb

2

Una pregunta interesante, pero es LINQ sobre consultar y lo que estamos haciendo aquí no se parece mucho a una consulta para mí. Incluso si hay una solución, no estoy seguro de que use Linq para algo como esto.

+1

No estoy de acuerdo, de hecho es una consulta, pero una consulta con efectos secundarios. Estoy preguntando para devolver cada elemento de una lista , entonces puedo establecer esos valores. Hay muchas consultas de este tipo utilizadas en Linq, como la proyección de transfrmación, etc. Realmente no veo cómo esto es diferente. –

+4

No hay una sola consulta en LINQ que modifique la colección consultada (de ahí "consulta"). – dtb

+0

nada que modifique el original, pero creo que lo que está tratando de lograr se puede hacer ... – bytebender

0

¿Puede describir algunos casos de uso de cómo propone utilizar dicho delegado?

Es decir, si PopulateChanges() le devuelve una lista <> de matrices DateTime, y las está examinando y configurándolas en DateTime.MinValue, ¿cuál es exactamente la unidad de código que desea colocar? el delegado?

+0

Todo lo que hago es crear un ejemplo de trabajo, como dice mi FYI. Realmente estoy buscando solo la parte de bucle for (el resto es solo configuración) en un área que es diferente a esta. Tengo otra lista que contiene los datos, esto simplemente asigna cada elemento de la matriz de cadenas a la hora de la última modificación. Cuando los cambios se borran, necesito restablecer los tiempos a MinValue. Cuando ocurren nuevos cambios, esos elementos obtienen un nuevo DateTime. –

0

Siempre hay mejores prácticas y eso, pero no sé si estoy de acuerdo con todo lo que todo el mundo ha dicho ...

Si he entendido bien lo que tiene que enumerar su matriz anidada por varias razones diferentes, y le gustaría encapsular esa funcionalidad para ser reutilizado .. Hay varias maneras diferentes para realizar pero aquí es uno usando LINQ y otro con salida ...

List<DateTime[]> changes = new List<DateTime[]>(); 
changes = PopulateChanges(); 

// *** As pointed out ForEach this will not change the value in the array, Thanks!*** 
changes.ForEach(change => change.ToList().ForEach(date => date = DateTime.MinValue)); 

// this how ever works but is kind of confusing... 
changes = changes.Select(change => change.Select(date => DateTime.MinValue).ToArray()).ToList(); 
//Even that would get old writing it over and over again... 

lo haría de esta manera ...

private void ForEachOnNestedDates(List<DateTime[]> list, Func<DateTime, DateTime> method) 
{ 
    // Use your code... 
    for (int i = 0; i < list.Count; i++) 
    { 
     for(int j = 0; j < list[i].Length; j++) 
     { 
      list[i][j] = method.Invoke(list[i][j]); 
     } 
    } 
} 

esto le permitiría volver a utilizar esto y hacer cosas diferentes para cada elemento. ex.

//Add a Day to each datetime value 
ForEachOnNestedDates(changes, (DateTime date) => date.AddDays(1)); 

//You also make it even more readable 
ForEachOnNextedDates(changes, DoSomethingWithDate); 

private DateTime DoSomethingWithDate(DateTime value) 
{ 

} 

Esto se usaría para el paso a realizar en cada fecha y hora a diferencia de lo hecho con cada fecha y hora ... Eso sería un poco diferente.

+2

La asignación de un valor a un parámetro de una lambda no cambia la colección consultada ... – dtb

+0

Corregido. La segunda opción debería funcionar ... – bytebender

Cuestiones relacionadas