Aller au contenu

Evaluer des conditions sur un ensemble de valeurs

all() : vérifier toutes les valeurs

all() renvoie True si chaque élément est considéré comme vrai. Elle s'arrête dès qu'elle rencontre une valeur fausse.

numbers = [2, 4, 6]
print(all(number % 2 == 0 for number in numbers))  # True
print(all([]))  # True

Equivalent en C#

int[] numbers = { 2, 4, 6 };
Console.WriteLine(numbers.All(n => n % 2 == 0)); // True
Console.WriteLine(Array.Empty<int>().All(n => n > 0)); // True

Les deux opérations s’arrêtent dès qu’un test échoue et renvoient vrai pour une séquence vide. LINQ All() exige un prédicat ; Python peut aussi tester directement la vérité de chaque élément.

any() : vérifier au moins une valeur

any() renvoie True dès qu'un élément est considéré comme vrai.

numbers = [3, 5, 8]
print(any(number % 2 == 0 for number in numbers))  # True
print(any([]))  # False

Les expressions génératrices utilisées ici produisent les résultats des tests au fur et à mesure.

Equivalent en C#

int[] numbers = { 3, 5, 8 };
Console.WriteLine(numbers.Any(n => n % 2 == 0)); // True
Console.WriteLine(Array.Empty<int>().Any());     // False

Any(predicate) recherche une correspondance. Any() sans prédicat teste seulement la présence d’éléments : [0] donne False avec any() en Python, alors que new[] { 0 }.Any() donne true.

len() : connaître la taille

len() renvoie le nombre d'éléments d'un objet qui possède une taille : chaîne, liste, dictionnaire, etc. Elle ne s'applique pas à tout itérable ; un générateur, par exemple, n'a généralement pas de taille accessible ainsi.

print(len("Python"))            # 6
print(len([10, 20, 30]))        # 3
print(len({"a": 1, "b": 2}))  # 2

Equivalent en C#

Console.WriteLine("Python".Length);              // 6
Console.WriteLine(new List<int> { 10, 20 }.Count); // 2
Console.WriteLine("😀".Length);                  // 2
Console.WriteLine("😀".EnumerateRunes().Count()); // 1

Length ou Count est préférable pour une collection connue. LINQ Count() peut parcourir une séquence qui ne possède pas de taille accessible. len("😀") donne 1 : Python compte les points de code, alors que string.Length compte les unités UTF-16. Aucun de ces décomptes ne représente toujours les caractères perçus visuellement.

range() : représenter une suite d'entiers

range() représente une progression arithmétique sans stocker une liste de toutes ses valeurs. La borne de fin est exclue et le pas ne peut pas être nul.

print(list(range(4)))          # [0, 1, 2, 3]
print(list(range(2, 9, 2)))    # [2, 4, 6, 8]
print(list(range(3, 0, -1)))   # [3, 2, 1]

Un objet range est une séquence réutilisable, pas un itérateur consommable.

Equivalent en C#

Console.WriteLine(string.Join(", ", Enumerable.Range(0, 4))); // 0, 1, 2, 3
var evens = Enumerable.Range(0, 4).Select(i => 2 + i * 2);
Console.WriteLine(string.Join(", ", evens)); // 2, 4, 6, 8
for (int i = 3; i > 0; i--)
    Console.WriteLine(i);

Enumerable.Range(start, count) reçoit un nombre d’éléments, pas une borne de fin. Il ne possède pas de paramètre de pas. Une projection ou une boucle exprime les autres progressions.

enumerate() : associer un indice à chaque élément

languages = ["Python", "C#", "Java"]

for index, language in enumerate(languages, start=1):
    print(index, language)
# 1 Python
# 2 C#
# 3 Java

Le compteur commence à zéro si start n'est pas précisé.

Equivalent en C#

string[] languages = { "Python", "C#", "Java" };
foreach (var item in languages.Select((value, index) => (Index: index + 1, Value: value)))
    Console.WriteLine($"{item.Index} {item.Value}");

La surcharge indexée de Select() fournit un indice commençant à zéro. Nous ajoutons ici 1 pour reproduire start=1. Une boucle for constitue une autre solution.

zip() : parcourir plusieurs itérables ensemble

zip() produit des tuples contenant un élément de chaque itérable. Par défaut, le parcours s'arrête lorsque le plus court est épuisé.

names = ["Clavier", "Souris"]
prices = [69.90, 24.90]

for name, price in zip(names, prices, strict=True):
    print(f"{name} : {price:.2f} €")

Avec strict=True, une différence de longueur provoque ValueError au moment où elle est détectée pendant le parcours. Cette option existe depuis Python 3.10.

Equivalent en C#

string[] names = { "Clavier", "Souris" };
double[] prices = { 69.90, 24.90 };
if (names.Length != prices.Length)
    throw new ArgumentException("Les longueurs diffèrent.");
foreach (var (name, price) in names.Zip(prices))
    Console.WriteLine($"{name} : {price:F2} €");

LINQ Zip() s’arrête au plus court, comme Python sans strict=True. Le contrôle montré reproduit l’exigence de longueur pour deux tableaux. Avec des séquences générales, il faut une stratégie adaptée ; les compter peut les consommer ou répéter leur exécution.

map() : transformer chaque élément

map() applique une fonction aux éléments parcourus. Elle peut aussi recevoir plusieurs itérables ; la fonction doit alors accepter autant d'arguments.

numbers = [2, 4, 6]
doubled = map(lambda number: number * 2, numbers)
print(list(doubled))  # [4, 8, 12]

Une compréhension de liste exprime souvent ce traitement plus directement :

doubled = [number * 2 for number in numbers]

Depuis Python 3.14, map() accepte aussi strict=True pour signaler des longueurs différentes lors d'un parcours de plusieurs itérables.

Equivalent en C#

int[] numbers = { 2, 4, 6 };
IEnumerable<int> query = numbers.Select(n => n * 2);
List<int> doubled = query.ToList();
Console.WriteLine(string.Join(", ", doubled)); // 4, 8, 12

Select() est l’équivalent courant d’une projection. Un objet Python map est un itérateur consommable ; une requête LINQ est souvent réénumérable et réexécute alors la projection, si sa source le permet. ToList() matérialise les résultats.

filter() : sélectionner des éléments

filter() conserve les éléments pour lesquels la fonction de test renvoie une valeur vraie.

numbers = [12, 7, 25, 8]
evens = filter(lambda number: number % 2 == 0, numbers)
print(list(evens))  # [12, 8]

Avec None comme fonction, les éléments eux-mêmes sont testés :

print(list(filter(None, [0, 1, "", "Python", None])))
# [1, 'Python']

Equivalent en C#

int[] numbers = { 12, 7, 25, 8 };
List<int> evens = numbers.Where(n => n % 2 == 0).ToList();
Console.WriteLine(string.Join(", ", evens)); // 12, 8

Where() correspond au filtrage par prédicat. C# ne possède pas de test général de vérité équivalent à filter(None, iterable) ; il faut exprimer la condition selon les types manipulés.

sorted() : obtenir une liste triée

sorted() construit une nouvelle liste sans modifier la collection source. reverse=True inverse l'ordre et key fournit un critère de tri.

numbers = [12, 7, 25, 8]
print(sorted(numbers))                # [7, 8, 12, 25]
print(sorted(numbers, reverse=True))  # [25, 12, 8, 7]
print(sorted(["Souris", "PC", "Clavier"], key=len))
# ['PC', 'Souris', 'Clavier']

Le tri est stable : des éléments dont les clés de tri sont égales conservent leur ordre relatif.

Equivalent en C#

int[] numbers = { 12, 7, 25, 8 };
List<int> ascending = numbers.OrderBy(n => n).ToList();
List<int> descending = numbers.OrderByDescending(n => n).ToList();
var words = new[] { "Souris", "PC", "Clavier" }.OrderBy(s => s.Length).ToList();

OrderBy() et OrderByDescending() conservent la source et fournissent un tri stable. Ils diffèrent de List<T>.Sort(), qui trie sur place. sorted() renvoie immédiatement une liste ; la requête LINQ est différée avant sa matérialisation. L’ordre des chaînes .NET dépend du comparateur ; StringComparer.Ordinal utilise les unités UTF-16 et ne reproduit pas tout ordre Unicode Python.

reversed() : parcourir en sens inverse

reversed() renvoie un itérateur inversé pour un objet compatible, notamment une séquence. Elle ne modifie pas cet objet et n'accepte pas tous les itérables.

numbers = [10, 20, 30]
print(list(reversed(numbers)))  # [30, 20, 10]

Equivalent en C#

int[] numbers = { 10, 20, 30 };
var reversed = numbers.Reverse().ToList();
Console.WriteLine(string.Join(", ", reversed)); // 30, 20, 10

LINQ Enumerable.Reverse() conserve la source. List<T>.Reverse() modifie au contraire la liste et renvoie void. Pour obtenir le comportement LINQ sur une liste, utilisons list.AsEnumerable().Reverse().

iter() : obtenir un itérateur

iter() donne accès au parcours explicite d'un itérable.

iterator = iter([10, 20])
print(next(iterator))  # 10
print(next(iterator))  # 20

Une seconde forme, iter(callable, stop_value), appelle une fonction sans argument jusqu'à obtenir une valeur égale à stop_value. Cette dernière n'est pas produite.

values = iter([10, 20, 0, 30])
print(list(iter(lambda: next(values), 0)))  # [10, 20]

Equivalent en C#

IEnumerable<int> numbers = new[] { 10, 20 };
using IEnumerator<int> iterator = numbers.GetEnumerator();
while (iterator.MoveNext())
    Console.WriteLine(iterator.Current);

IEnumerable<T> et IEnumerator<T> correspondent aux rôles d’itérable et d’itérateur. La forme Python à deux arguments n’a pas de primitive C# identique : une boucle ou une méthode avec yield return peut la reproduire.

next() : obtenir l'élément suivant

next() fait avancer un itérateur. Lorsqu'il est épuisé, elle lève StopIteration, sauf si une valeur de remplacement est fournie.

iterator = iter([10])
print(next(iterator))        # 10
print(next(iterator, None))  # None

Equivalent en C#

using IEnumerator<int> iterator = ((IEnumerable<int>)new[] { 10 }).GetEnumerator();
if (iterator.MoveNext())
    Console.WriteLine(iterator.Current); // 10
int? nextValue = iterator.MoveNext() ? iterator.Current : null;
Console.WriteLine(nextValue is null);    // True

C# sépare l’avancement (MoveNext()) de la lecture (Current). La fin de parcours est indiquée par false. Current ne doit pas être lu avant le premier avancement réussi ni après la fin.

slice() : construire une tranche

Un objet slice représente les bornes et le pas d'une extraction. Il peut être réutilisé sur plusieurs séquences.

selection = slice(1, 5, 2)
print([10, 20, 30, 40, 50][selection])  # [20, 40]

Cette sélection correspond à [1:5:2].

Equivalent en C#

int[] numbers = { 10, 20, 30, 40, 50 };
int[] selected = numbers.Skip(1).Take(4)
    .Where((value, index) => index % 2 == 0).ToArray();
Console.WriteLine(string.Join(", ", selected)); // 20, 40
int[] contiguous = numbers[1..4]; // 20, 30, 40

Les plages C# Range expriment des portions contiguës, sans paramètre de pas. Leur utilisation sur un tableau crée un nouveau tableau. Pour une vue sans copie, utilisons Span<T> ; pour des pas ou bornes négatifs Python, une adaptation explicite est nécessaire.