179 votes

Quelle est l'utilité de la méthode d'extension Enumerable.Zip dans Linq ?

Quelle est l'utilité de Enumerable.Zip méthode d'extension dans Linq ?

262voto

geek Points 7054

L'opérateur Zip fusionne les éléments correspondants de deux séquences en utilisant une fonction de sélection spécifiée.

var letters= new string[] { "A", "B", "C", "D", "E" };
var numbers= new int[] { 1, 2, 3 };
var q = letters.Zip(numbers, (l, n) => l + n.ToString());
foreach (var s in q)
    Console.WriteLine(s);

Ouput

A1
B2
C3

124voto

Jason Points 125291

Zip permet de combiner deux séquences en une seule. Par exemple, si vous avez les séquences

1, 2, 3

y

10, 20, 30

et vous voulez la séquence qui est le résultat de la multiplication des éléments dans la même position dans chaque séquence pour obtenir

10, 40, 90

vous pourriez dire

var left = new[] { 1, 2, 3 };
var right = new[] { 10, 20, 30 };
var products = left.Zip(right, (m, n) => m * n);

On l'appelle "zip" parce qu'il faut considérer une séquence comme le côté gauche d'une fermeture à glissière, et l'autre séquence comme le côté droit de la fermeture à glissière, et l'opérateur zip va tirer les deux côtés ensemble en appariant les dents (les éléments de la séquence) de manière appropriée.

24voto

Justin Morgan Points 12853

Il itère à travers deux séquences et combine leurs éléments, un par un, en une seule nouvelle séquence. Ainsi, on prend un élément de la séquence A, on le transforme avec l'élément correspondant de la séquence B, et le résultat forme un élément de la séquence C.

Une façon d'y penser est que c'est similaire à Select sauf qu'au lieu de transformer les éléments d'une seule collection, il travaille sur deux collections à la fois.

De la Article MSDN sur la méthode :

int[] numbers = { 1, 2, 3, 4 };
string[] words = { "one", "two", "three" };

var numbersAndWords = numbers.Zip(words, (first, second) => first + " " + second);

foreach (var item in numbersAndWords)
    Console.WriteLine(item);

// This code produces the following output:

// 1 one
// 2 two
// 3 three

Si vous deviez faire cela en code impératif, vous feriez probablement quelque chose comme ceci :

for (int i = 0; i < numbers.Length && i < words.Length; i++)
{
    numbersAndWords.Add(numbers[i] + " " + words[i]);
}

Ou si LINQ n'avait pas Zip en elle, vous pourriez faire ça :

var numbersAndWords = numbers.Select(
                          (num, i) => num + " " + words[i]
                      );

C'est utile lorsque les données sont réparties dans des listes simples, semblables à des tableaux, ayant toutes la même longueur et le même ordre, et décrivant chacune une propriété différente du même ensemble d'objets. Zip vous aide à rassembler ces éléments de données en une structure plus cohérente.

Ainsi, si vous disposez d'un tableau de noms d'États et d'un autre tableau de leurs abréviations, vous pouvez les regrouper dans un fichier State comme ça :

IEnumerable<State> GetListOfStates(string[] stateNames, int[] statePopulations)
{
    return stateNames.Zip(statePopulations, 
                          (name, population) => new State()
                          {
                              Name = name,
                              Population = population
                          });
}

22voto

CodingYoshi Points 17416

NE PAS laisser le nom Zip vous déstabiliser. Cela n'a rien à voir avec le fait de zipper un fichier ou un dossier (compression). En fait, son nom provient du fonctionnement de la fermeture à glissière d'un vêtement : La fermeture à glissière des vêtements a deux côtés et chaque côté a un tas de dents. Lorsque vous allez dans une direction, la fermeture à glissière énumère (parcourt) les deux côtés et ferme la fermeture en serrant les dents. Lorsque vous allez dans l'autre sens, elle ouvre les dents. Vous vous retrouvez avec une fermeture à glissière ouverte ou fermée.

C'est la même idée avec le Zip méthode. Prenons un exemple où nous avons deux collections. L'une contient des lettres et l'autre contient le nom d'un aliment qui commence par cette lettre. Pour des raisons de clarté, je les appelle leftSideOfZipper y rightSideOfZipper . Voici le code.

var leftSideOfZipper = new List<string> { "A", "B", "C", "D", "E" };
var rightSideOfZipper = new List<string> { "Apple", "Banana", "Coconut", "Donut" };

Notre tâche consiste à produire une collection dont la lettre du fruit est séparée par un signe : et son nom. Comme ceci :

A : Apple
B : Banana
C : Coconut
D : Donut

Zip à la rescousse. Pour rester dans la terminologie de notre fermeture éclair, nous appellerons ce résultat closedZipper et les éléments de la fermeture éclair de gauche que nous appellerons leftTooth et le côté droit que nous appellerons righTooth pour des raisons évidentes :

var closedZipper = leftSideOfZipper
   .Zip(rightSideOfZipper, (leftTooth, rightTooth) => leftTooth + " : " + rightTooth).ToList();

Dans l'exemple ci-dessus, nous énumérons (voyageons) le côté gauche de la fermeture à glissière et le côté droit de la fermeture à glissière et effectuons une opération sur chaque dent. L'opération que nous effectuons est la concaténation de la dent gauche (lettre alimentaire) avec une lettre : et ensuite la dent de droite (nom de l'aliment). Nous faisons cela en utilisant ce code :

(leftTooth, rightTooth) => leftTooth + " : " + rightTooth)

Le résultat final est le suivant :

A : Apple
B : Banana
C : Coconut
D : Donut

Qu'est-il arrivé à la dernière lettre E ?

Si vous êtes en train d'énumérer (tirer) une vraie fermeture à glissière de vêtements et qu'un côté, peu importe le côté gauche ou le côté droit, a moins de dents que l'autre côté, que se passera-t-il ? Eh bien, la fermeture s'arrêtera là. Le site Zip fera exactement la même chose : il s'arrêtera lorsqu'il aura atteint le dernier élément de chaque côté. Dans notre cas, le côté droit a moins de dents (noms des aliments), il s'arrêtera donc à "Donut".

17voto

XAleXOwnZX Points 159

Beaucoup de réponses ici démontrent Zip mais sans vraiment expliquer un cas d'utilisation réel qui motiverait l'utilisation de l'outil. Zip .

Un modèle particulièrement commun qui Zip est fantastique pour itérer sur des paires successives de choses. Ceci est fait en itérant une énumérable X avec lui-même, en sautant 1 élément : x.Zip(x.Skip(1) . Exemple visuel :

 x | x.Skip(1) | x.Zip(x.Skip(1), ...)
---+-----------+----------------------
   |    1      |
 1 |    2      | (1, 2)
 2 |    3      | (2, 1)
 3 |    4      | (3, 2)
 4 |    5      | (4, 3)

Ces paires successives sont utiles pour trouver les premières différences entre les valeurs. Par exemple, les paires successives de IEnumable<MouseXPosition> peut être utilisé pour produire IEnumerable<MouseXDelta> . De même, les échantillons bool valeurs de l'a button peuvent être interprétés comme des événements tels que NotPressed / Clicked / Held / Released . Ces événements peuvent alors conduire à des appels à des méthodes déléguées. Voici un exemple :

using System;
using System.Collections.Generic;
using System.Linq;

enum MouseEvent { NotPressed, Clicked, Held, Released }

public class Program {
    public static void Main() {
        // Example: Sampling the boolean state of a mouse button
        List<bool> mouseStates = new List<bool> { false, false, false, false, true, true, true, false, true, false, false, true };

        mouseStates.Zip(mouseStates.Skip(1), (oldMouseState, newMouseState) => {
            if (oldMouseState) {
                if (newMouseState) return MouseEvent.Held;
                else return MouseEvent.Released;
            } else {
                if (newMouseState) return MouseEvent.Clicked;
                else return MouseEvent.NotPressed;
            }
        })
        .ToList()
        .ForEach(mouseEvent => Console.WriteLine(mouseEvent) );
    }
}

Imprimés :

NotPressesd
NotPressesd
NotPressesd
Clicked
Held
Held
Released
Clicked
Released
NotPressesd
Clicked

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X