Remplacement de for… si itération du tableau
Question
J'adore les compréhensions de listes en Python, car elles représentent de manière concise une transformation d'une liste.
Cependant, dans d’autres langues, je me retrouve fréquemment à écrire quelque chose du genre :
foreach (int x in intArray)
if (x > 3) //generic condition on x
x++
//do other processing
Cet exemple est en C#, où j'ai l'impression que LINQ peut vous aider, mais existe-t-il une construction de programmation commune qui peut remplacer cette solution légèrement moins élégante ?Peut-être une structure de données que je n'envisage pas ?
La solution
L'incrément dans l'original foreach
la boucle n'affectera pas le contenu du tableau, la seule façon de le faire reste un for
boucle:
for(int i = 0; i < intArray.Length; ++i)
{
if(intArray[i] > 3) ++intArray[i];
}
Linq n'est pas destiné à modifier les collections ou séquences existantes.Il crée de nouvelles séquences basées sur celles existantes.Il est possible d'obtenir le code ci-dessus en utilisant Linq, bien que cela soit légèrement contraire à son objectif :
var newArray1 = from i in intArray select ((i > 3) ? (i + 1) : (i));
var newArray2 = intArray.Select(i => (i > 3) ? (i + 1) : (i));
En utilisant where
(ou équivalent), comme indiqué dans certaines des autres réponses, exclura toutes les valeurs inférieures ou égales à 3 de la séquence résultante.
var intArray = new int[] { 10, 1, 20, 2 };
var newArray = from i in intArray where i > 3 select i + 1;
// newArray == { 11, 21 }
Il y a un ForEach
méthode sur les tableaux qui vous permettra d'utiliser une fonction lambda au lieu d'un foreach
bloc, mais pour autre chose qu'un appel de méthode, je m'en tiendrai à foreach
.
intArray.ForEach(i => DoSomething(i));
Autres conseils
En C#, vous pouvez appliquer un traitement sélectif sur tout ce qui se trouve à l'intérieur d'un IEnumerable comme ceci :
intArray.Where(i => i > 3).ConvertAll();
DoStuff(intArray.Where(i => i 3));
Etc..
En Python, vous avez filtrer et cartographier, ce qui peut faire ce que vous voulez :
map(lambda x: foo(x + 1) filter(lambda x: x > 3, intArray))
Il y a aussi compréhensions de listes qui peut faire les deux en une seule déclaration simple :
[f(x + 1) for x in intArray if x > 3]
en Ruby :
intArray.select { |x| x > 3 }.each do |x|
# do other processing
end
ou si « autre traitement » est une courte phrase :
intArray.select { |x| x > 3 }.each { |x| something_that_uses x }
enfin, si vous souhaitez renvoyer un nouveau tableau contenant les résultats du traitement des éléments supérieurs à 3 :
intArray.select { |x| x > 3 }.map { |x| do_something_to x }
map(lambda x: test(x + 1) filter(lambda x: x > 3, arr))
Cela dépend de la langue et de ce que vous devez faire, une « carte », comme on l'appelle dans de nombreuses langues, pourrait être ce que vous recherchez.Je ne connais pas C#, mais d'après ce page, .NET 2.0 appelle la carte "ConvertAll".
La signification de « carte » est assez simple : prenez une liste et appliquez une fonction à chaque élément de celle-ci, renvoyant une nouvelle liste.Vous recherchez peut-être également "filtre", qui vous donnerait une liste d'éléments qui satisfont à un prédicat dans une autre liste.