11
votes

Créer des éléments à partir de 3 collections à l'aide de LINQ

J'ai 3 collections avec exactement les mêmes articles comptent.

J'ai besoin de créer une nouvelle collection basée sur ces 3 valeurs d'élément de collections. P>

Exemple: P>

    var query = from pt in list1
                from at in list2
                from ct in list3
                select new Item
                           {
                               Value1 = pt,
                               Value2 = at,
                               Value3 = ct
                           };


6 commentaires

Attendez - quand as-tu eu une exception exceptionnelle? La requête que vous avez montrée n'exécute rien . Les nouveaux articles seront créés lorsque vous pourrespirez-les sur eux. Cela ne devrait pas causer de surprise à moins que vous ne gardez chaque article en mémoire.


@Judah, je reçois une exception exceptionnelle après avoir appelé .tolist ()


Ouais, parce que vous créez tous les éléments de la mémoire. Pouvez-vous éviter d'appeler .tolist ()? Encore mieux, peut List1, List2 et List3 Be de type iEnumerable , plutôt que de la liste? Si vous utilisez une exécution différée, vous ne conserverez pas tous les articles en mémoire et vous ne toucherez donc pas une exception exceptionnelle.


La raison pour laquelle vous manquez de mémoire est que vous faites un produit cartésien de trois listes, plutôt que de les traiter comme des matrices parallèles. Cela signifie que vous obtenez les résultats d'une boucle triple imbriquée plutôt que des résultats d'une boucle à l'aide du même index pour les trois listes. Python a une fonction zip qui prend un nombre de collections et renvoie une collection de tuples. La fonction zip de LINQ essaie (et échoue) à faire de même, car elle n'autorise que deux séquences à la fois et nécessite une fonction de transformation. Fonctionne OK pour deux listes, mais 3+ est un cauchemar.


Bonne réponse à Stackoverflow.com/a/14639590/116891


Dupliqué possible de Fusionner plusieurs listes dans une liste avec Linq


7 Réponses :


11
votes

Étant donné que vous parlez de Liste (qui a une index rapide), et vous fournissez la garantie que les trois listes sont de même longueur, le moyen le plus simple serait: < Pré> xxx

Cette approche ne fonctionnera évidemment pas bien avec les collections qui ne prennent pas en charge les indexateurs rapides. Une approche plus générale consisterait à écrire une méthode zip3 , telle que celle fournie avec le module F # COLLECITIONS.SEQ : SEQ.ZIP3 <'T1,' T2, 'T3> . Sinon, vous pouvez chaîner deux énumérable.zip appelle ensemble pour produire un comportement similaire (comme mentionné dans d'autres réponses), bien que cela semble assez moche.


1 commentaires

C'était une réponse utile.



2
votes

Un peu minable mais cela devrait fonctionner. XXX


0 commentaires

7
votes

vous pouvez zip eux ensemble - Ceci est zipping up premier list2 et list3, puis ferme la liste combinée avec la liste1: xxx


0 commentaires

0
votes

Vous pouvez essayer quelque chose comme ce qui suit:

 var combined = list1.Select((x, i) => new Item {Value1 = x, Value2 = list2.ElementAt(i), list3 = range3.ElementAt(i)});


0 commentaires

0
votes

Si vous êtes sûr que toutes les listes ont une taille égale, vous devez utiliser une boucle pour la boucle:

        List<Item> combinedList = new List<Item>(list1.Count);

        for (int i = 0; i < list1.Count; i++)
        {
            combinedList.Add(new Item()
            {
                Value1 = list1[i],
                Value2 = list2[i],
                Value3 = list3[i]
            });
        }


1 commentaires

Mais contrairement au lien, ce n'est pas chargé paresseusement; Tous les articles sont ajoutés en un seul passage. Étant donné qu'il ressent déjà des exceptions de mémoire, cela fera pire le problème.



4
votes

Le concept de Cartographie des séquences ou des listes dans les arguments des fonctions Originaire du langage de programmation LISP, un peu plus de 50 ans. Dans Lisp, il est trivial en raison de sa nature non collée et axée sur la liste. Mais, le faire dans une langue fortement saisie est difficile, du moins en termes de résolution du problème général des séquences de mappage n à une fonction qui prend n arguments.

Voici un faible poignau à ce qui devrait accueillir la plupart des besoins: xxx


0 commentaires

3
votes

Voici une version simplifiée qui prend tout numéro de séquences (en tant que tableau) du même type et les transmises ensemble: xxx

pros
  • Nombre de séquences
  • Quatre lignes de code
  • Une autre surcharge pour Linq .zip () méthode
  • zips toutes les séquences à la fois au lieu de chaînage .zip pour ajouter une séquence de plus chaque fois

    contre
    • Même type requis pour toutes les séquences (pas un problème dans de nombreuses situations)
    • pas de vérification de la même longueur de la liste (ajoutez une ligne si vous en avez besoin)

      Utilisation

       Couleurs de zippation


0 commentaires