Reemplazo de for… si se trata de una iteración de matriz
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?
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.