IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

comment remplacer un foreach par du LINQ ?


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Inscrit en
    Novembre 2004
    Messages
    417
    Détails du profil
    Informations forums :
    Inscription : Novembre 2004
    Messages : 417
    Par défaut comment remplacer un foreach par du LINQ ?
    Bonjour,
    J'ai actuellement ceci qui fonctionne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public void func(Division[] divisions)
    {
        var currencies = new HashSet<string>(divisions.SelectMany(div => div.Locations).Select(e => e.CcyLoc));
        //currencies.UnionWith(new HashSet<string>(divisions.SelectMany(div => div.CurrencyCode)));
        //ou bien même
        //currencies.UnionWith(divisions.SelectMany(div => div.CcyDiv));
        foreach(CalcDivision div in divisions) {
            currencies.Add(div.CurrencyCode);
        }
    }
    Mais je ne comprends pas pourquoi je ne peux pas remplacer mon foreach par un des lignes commentée du dessus. Ça ne compile pas (invalid arguments).
    Voyez-vous le problème?
    D'avance merci,
    Julien

  2. #2
    Membre chevronné Avatar de Shivaneth
    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2004
    Messages
    349
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 40
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2004
    Messages : 349
    Par défaut
    Bonjour,

    essaye ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        var currencies = new HashSet<string>(divisions.SelectMany(div => div.Locations).Select(e => e.CcyLoc));
        currencies.AddRange((from d in divisions select d.CurrencyCode).ToList());
        //ou
        currencies.AddRange(divisions.Select(d=>d.CurrencyCode));

  3. #3
    Membre Expert
    Avatar de Sehnsucht
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Octobre 2008
    Messages
    847
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Lot et Garonne (Aquitaine)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Octobre 2008
    Messages : 847
    Par défaut
    @Shiva Skunk: et la méthode HashSet<T>.AddRange ; tu la sors du chapeau ?

    en partant du principe que CurrencyCode et CcyDiv sont bien des string ; le fait de faire un SelectMany dessus renvoie alors un IEnumerable<char> car SelectMany sert à "aplatir" une collection de collections (et un string est un IEnumerable<char>) ; comme tu l'as fait pour "aplatir" l'ensemble des CcyLoc contenus dans tous les Locations. Du coup, a priori (parce qu'il faut quand même faire pas mal de "divination" pour savoir qui fait quoi avec le peu d'infos ), remplace ces SelectMany par des Select et ça devrait aller (il faudra peut-être un ajout de Cast ou OfType pour le CurrencyCode vu qu'il semblerait que tu l'obtiennes de CalcDivision plutôt que Division [et que je suppose que le premier hérite du second]).

    Sur un autre plan, le foreach c'était déjà très bien à la base ; faut arrêter de vouloir à tout prix mettre du Linq parce que c'est "hype" (UnionWith fait juste un foreach avec un AddIfNotPresent (une méthode interne à la classe) même méthode appelée depuis Add ; donc tu gagnes juste un passage par Add).

    Cordialement !

  4. #4
    Membre chevronné Avatar de Shivaneth
    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2004
    Messages
    349
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 40
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2004
    Messages : 349
    Par défaut
    Rho bah si on peut plus se réveiller tranquillement le matin aussi

    désolée :red:

  5. #5
    Membre émérite Avatar de worm83
    Homme Profil pro
    Architecte logiciel
    Inscrit en
    Février 2010
    Messages
    459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Architecte logiciel
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2010
    Messages : 459
    Par défaut
    Bonjour,

    Tu peux recréer la méthode d'extension ForEach comme ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
     
     public static void Foreach<T>(this IEnumerable<T> li, Action<T> action)
            {
                foreach (var x in li)
                {
                    action(x);
                }
            }


    Ce qui donne à l'utilisation

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     
    public void UneAction(IEnumerable<string> li)
    {
           li.ForEach( x => Console.Writeline(x));
    }
    Ça reste un foreach mais écrit de facon "Linq".


    Edit : Je viens de remarquer que tu avais déjà posté la question et que quelqu'un avait répondu la même chose que moi.

  6. #6
    Membre éclairé
    Inscrit en
    Novembre 2004
    Messages
    417
    Détails du profil
    Informations forums :
    Inscription : Novembre 2004
    Messages : 417
    Par défaut
    C'est pas que je cherche à faire du LINQ à tout prix, je cherche juste à comprendre.
    Effectivement, je me suis trompé: CcyLoc, CurrencyCode et CcyDiv sont les mêmes string en fait mais je ne peux plus modifier mon post.
    AddRange n'est effectivement pas accessible.
    Effectivement Select fonctionne quand SelectMany ne fonctionne pas, c'est un peu tricky cette "mise à plat" que fait SelectMany pour passer d'un type string à un IEnumerable de char.. Dans ma 1ère ligne "SelectMany(div => div.Locations)", comment est-ce qu'il sait qu'il ne doit s'arrêter à retourner des Locations et pas d'autres types qui composent mes Locations?
    Y a-t-il une différence à faire currencies.UnionWith(new HashSet<string>(divisions.Select(div => div.CurrencyCode))); ou currencies.UnionWith(divisions.Select(div => div.CurrencyCode)); ?

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. comment remplacer un foreach par du LINQ ?
    Par jmclej dans le forum Linq
    Réponses: 8
    Dernier message: 01/12/2014, 13h52
  2. [VB.NET] Comment remplacer une couleur par une autre?
    Par jazz matazz dans le forum VB.NET
    Réponses: 5
    Dernier message: 11/02/2006, 14h29
  3. Comment remplacer le clavier par des boutons ?
    Par aliwassem dans le forum Langage
    Réponses: 1
    Dernier message: 14/12/2005, 19h00
  4. Réponses: 5
    Dernier message: 30/05/2005, 16h58

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo