Pregunta

Me encantan las listas por comprensión en Python porque representan de manera concisa una transformación de una lista.

Sin embargo, en otros idiomas, frecuentemente me encuentro escribiendo algo como:

foreach (int x in intArray)
  if (x > 3) //generic condition on x
    x++ 
    //do other processing

Este ejemplo está en C#, donde tengo la impresión de que LINQ puede ayudar con esto, pero ¿existe alguna construcción de programación común que pueda reemplazar esta solución poco elegante?¿Quizás una estructura de datos que no estoy considerando?

¿Fue útil?

Solución

El incremento en el original. foreach El bucle no afectará el contenido de la matriz, la única forma de hacerlo sigue siendo un for bucle:

for(int i = 0; i < intArray.Length; ++i)
{
    if(intArray[i] > 3) ++intArray[i];
}

Linq no pretende modificar colecciones o secuencias existentes.Crea nuevas secuencias basadas en las existentes.Es posible lograr el código anterior usando Linq, aunque va ligeramente en contra de sus propósitos:

var newArray1 = from i in intArray select ((i > 3) ? (i + 1) : (i));
var newArray2 = intArray.Select(i => (i > 3) ? (i + 1) : (i));

Usando where (o equivalente), como se muestra en algunas de las otras respuestas, excluirá cualquier valor menor o igual a 3 de la secuencia resultante.

var intArray = new int[] { 10, 1, 20, 2 };
var newArray = from i in intArray where i > 3 select i + 1;
// newArray == { 11, 21 }

Hay un ForEach método en matrices que le permitirá utilizar una función lambda en lugar de una foreach bloquear, aunque para algo más que una llamada a un método me quedaría con foreach.

intArray.ForEach(i => DoSomething(i));

Otros consejos

En C# puedes aplicar procesamiento selectivo a cualquier cosa que viva dentro de un IEnumerable como este:

intArray.Where(i => i > 3).ConvertAll();
DoStuff(intArray.Where(i => i 3));

Etc..

En Python tienes filtrar y mapear, que puede ser lo que quieras:

map(lambda x: foo(x + 1) filter(lambda x: x > 3, intArray))

También hay lista de comprensiones que puede hacer ambas cosas en una declaración sencilla:

[f(x + 1) for x in intArray if x > 3]

en rubí:

intArray.select { |x| x > 3 }.each do |x|
  # do other processing
end

o si "otro procesamiento" es una frase breve:

intArray.select { |x| x > 3 }.each { |x| something_that_uses x }

por último, si desea devolver una nueva matriz que contenga los resultados del procesamiento de aquellos elementos mayores que 3:

intArray.select { |x| x > 3 }.map { |x| do_something_to x }
map(lambda x: test(x + 1) filter(lambda x: x > 3, arr))

Depende del idioma y de lo que necesites hacer, un "mapa", como se le llama en muchos idiomas, podría ser lo que estás buscando.No sé C#, pero según este página, .NET 2.0 llama al mapa "ConvertAll".

El significado de "mapa" es bastante simple: tome una lista y aplique una función a cada elemento de ella, devolviendo una nueva lista.Es posible que también esté buscando "filtro", que le brindará una lista de elementos que satisfacen un predicado en otra lista.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top