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

Langage PHP Discussion :

array multidimensionnel : supprimer une entrée [PHP 7]


Sujet :

Langage PHP

  1. #1
    Membre régulier Avatar de RowanMayfair
    Femme Profil pro
    Développeuse Freelance
    Inscrit en
    mars 2019
    Messages
    242
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : France, Haute Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Développeuse Freelance

    Informations forums :
    Inscription : mars 2019
    Messages : 242
    Points : 85
    Points
    85
    Par défaut array multidimensionnel : supprimer une entrée
    Bonjour,

    Je sèche, sans comprendre ce qui cloche.

    J'ai 2 arrays :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    $foo =
    array (size=436)
      0 => 
        array (size=3)
          'id' => string '2459' (length=4)
          'prenom' => string 'bird' (length=4)
          'nom' => string 'Jean' (length=4)
     
      1 => 
        array (size=3)
          'id' => string '2444' (length=4)
          'prenom' => string 'Luc' (length=3)
          'nom' => string 'CestPasMoi' (length=10)
     
      2 => 
        array (size=3)
          'id' => string '2474' (length=4)
          'prenom' => string 'Steph' (length=5)
          'nom' => string 'CestMoi' (length=7)
      3 => 
        array (size=3)
          'id' => string '2446' (length=4)
          'prenom' => string 'Rasta' (length=5)
          'nom' => string 'CestLui' (length=6)
     
      4 => 
        array (size=3)
          'id' => string '2537' (length=4)
          'prenom' => string 'Thia' (length=4)
          'nom' => string 'CestElle' (length=8)
     
     
    $bar =
    array (size=8)
      0 => 
        array (size=2)
          'idCherche' => string '8' (length=1)
          'idUneAutre' => string '2459' (length=4)
      1 => 
        array (size=2)
          'idCherche' => string '8' (length=1)
          'idUneAutre' => string '2474' (length=4)
      2 => 
        array (size=2)
          'idCherche' => string '8' (length=1)
          'idUneAutre' => string '2537' (length=4)
    Dans $foo['id'], je voudrai supprimer les entrées qui correspondent à celles qui sont dans $bar['idUneAutre'].

    J'ai donc fait un truc comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    foreach($foo as $unFoo) {
            foreach($bar as $leBar) {
                if ($bar['idUneAutre'] == $foo['id']) {
                    unset($unFoo, $foo);
                }
            }        
        }
     
        return $foo;
    Mais ça ne fonctionne pas Wamp me répond
    Undefined variable: unFoo in c:\blablabla on line 145
    ça ne fonctionne pas comme ça unset ?
    où c'est autre chose ?

    D'avance merci pour vos éclairages

  2. #2
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    octobre 2006
    Messages
    8 800
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : octobre 2006
    Messages : 8 800
    Points : 4 268
    Points
    4 268
    Billets dans le blog
    1
    Par défaut
    Bonjour,
    il me semble que unset attend un seul paramètre, donc essaye unset($foo['id']);
    Il vaut mieux viser la perfection et la manquer que viser l'imperfection et l'atteindre. - Bertrand Russell

  3. #3
    Membre régulier Avatar de RowanMayfair
    Femme Profil pro
    Développeuse Freelance
    Inscrit en
    mars 2019
    Messages
    242
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : France, Haute Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Développeuse Freelance

    Informations forums :
    Inscription : mars 2019
    Messages : 242
    Points : 85
    Points
    85
    Par défaut
    Non ça ne fonctionnait pas non plus.

    Mais je viens de trouver une solution

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    for($i = 0; $i < count($foo); $i++) {
            for ($j = 0; $j < count($bar); $j++) {
                if($foo[$i]['id'] == $bar[$j]['idUneAutre']) {
                    array_splice($foo, $i, 1);
                }
            }
        }
    Déjà une boucle foreach n'était pas forcément adaptée.
    Et ensuite, array_splice c'est top en fait, ça te fait le petit découpage qui va bien.

    Merci

  4. #4
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    octobre 2006
    Messages
    8 800
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : octobre 2006
    Messages : 8 800
    Points : 4 268
    Points
    4 268
    Billets dans le blog
    1
    Par défaut
    Ca s'invente pas ; comment as-tu trouvé ?
    Il vaut mieux viser la perfection et la manquer que viser l'imperfection et l'atteindre. - Bertrand Russell

  5. #5
    Membre régulier Avatar de RowanMayfair
    Femme Profil pro
    Développeuse Freelance
    Inscrit en
    mars 2019
    Messages
    242
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : France, Haute Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Développeuse Freelance

    Informations forums :
    Inscription : mars 2019
    Messages : 242
    Points : 85
    Points
    85
    Par défaut
    Citation Envoyé par laurentSc Voir le message
    Ca s'invente pas ; comment as-tu trouvé ?
    Euh ben si ça s'invente drôle de remarque.
    J'ai passé 1 heure à tripoter mon bout de code dans tous les sens, avec des var_dump avant et après.

    En fait en parcourant avec une boucle for déjà ça m'a paru + clair (pour moi en tout cas), et sinon avec une recherche google j'avais lu qu'il y avait 2 solutions pour supprimer des éléments dans un array : unset et array_splice

    Donc ben voilà ....

  6. #6
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    mars 2009
    Messages
    2 413
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : mars 2009
    Messages : 2 413
    Points : 5 321
    Points
    5 321
    Par défaut
    Parcourir un tableau avec des boucles for, c'est un peu beaucoup la loose depuis l'apparition de foreach en php4, et même si ça fonctionne avec array_splice cette fonction est plutôt destinée à enlever un pan contiguë d'items d'un tableau que des items un par un.

    Il faut bien comprendre que par défaut une boucle foreach travaille sur des copies des items du tableau par sur les items eux-mêmes, c'est pourquoi unset($unFoo); n'effacera que la copie de l'item courant dans la boucle, mais que le tableau $foo restera inchangé.

    Il est possible de demander dans une boucle foreach de ne pas renvoyer une copie de l'item, mais bien une référence vers l'item du tableau en plaçant & devant le nom de la variable:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    foreach($foo as &$unFoo) {
        foreach($bar as $leBar) {
            if ( $leBar['idUneAutre'] == $unFoo['id'] ) {
                unset($unFoo);
                break; // l'item a été enlevé, on interrompt la boucle sur $bar
            }
        }        
    }
    Néanmoins, pas mal de développeurs n'aiment pas utiliser les références ou s'en méfient et préfèrent utiliser la clef de l'item que tu peux obtenir via foreach:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    foreach($foo as $k => $unFoo) {
        foreach($bar as $leBar) {
            if ( $leBar['idUneAutre'] == $unFoo['id'] ) {
                unset($foo[$k]);
                break; 
            }
        }        
    }



    Les boucles imbriquées c'est pas la panacée, car avec elles on augmente très vite les temps de traitements ( m items de tableau1 X n items du tableau2 ).
    Ce que tu peux faire à la place c'est extraire une bonne fois pour toutes les ids à enlever de $bar grâce à array_column puis de retourner le tableau obtenu avec array_flip. De cette manière, pour contrôler qu'une id est présente dans le tableau obtenu, il suffit de regarder si la clef (donc l'id) existe avec isset:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ids = array_flip(array_column($bar, 'idUneAutre'));
    $result = array_filter($foo, function ($item) use ($ids) { return !isset($ids[$item['id']]); });
    Et à partir de PHP 7.4, tu peux même écrire cette deuxième (et dernière) ligne comme ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $result = array_filter($foo, fn($item) => !isset($ids[$item['id']]));
    C'est pas beau la vie?
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  7. #7
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    mars 2009
    Messages
    2 413
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : mars 2009
    Messages : 2 413
    Points : 5 321
    Points
    5 321
    Par défaut
    Une alternative à l'utilisation conjuguée de array_flip et de isset (qui est un truc, une recette qu'on apprend avec la pratique pour pallier à la lenteur de in_array()) c'est d'activer le module Ds de PHP pour utiliser la classe Ds\Set:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $idSet = new \Ds\Set(array_column($bar, 'idUneAutre'));
    $result = array_filter($foo, fn($item) => !$idSet->contains($item['id']));
    Au delà du fait que Ds\Set est la structure de données appropriée pour représenter un ensemble, on aboutit à une code qui touche pratiquement au langage naturel: filtre les items du tableau $foo, lorsque leur id n'est pas contenu dans l'ensemble $idSet.
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  8. #8
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    octobre 2006
    Messages
    8 800
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : octobre 2006
    Messages : 8 800
    Points : 4 268
    Points
    4 268
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par CosmoKnacki Voir le message
    Il faut bien comprendre que par défaut une boucle foreach travaille sur des copies des items du tableau par sur les items eux-mêmes, c'est pourquoi unset($unFoo); n'effacera que la copie de l'item courant dans la boucle, mais que le tableau $foo restera inchangé.
    Je savais pas ; très instructif.

    Ta culture en PHP me laisse pantois...
    Il vaut mieux viser la perfection et la manquer que viser l'imperfection et l'atteindre. - Bertrand Russell

  9. #9
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    mars 2009
    Messages
    2 413
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : mars 2009
    Messages : 2 413
    Points : 5 321
    Points
    5 321
    Par défaut
    Citation Envoyé par laurentSc Voir le message
    Je savais pas ; très instructif.

    Ta culture en PHP me laisse pantois...
    Et encore, tu n'as pas vu ma culture des herbes aromatiques et des tomates qui est bien plus impressionnante!

    En fait c'est assez connu, et c'est le genre de chose qu'on apprend à ses dépens la plupart du temps en essayant justement de modifier ou d'enlever un item d'un tableau. C'est étrange que tu sois passé au travers, mais en même temps c'est le coup classique: l'instruction basique dont on se méfie pas et qu'on utilise tout le temps sans se poser de questions, et un jour paf! On ne comprend pas ce qui se passe ou alors on se décide à lire la page du manuel et on tombe des nues!
    Ça m'est arrivé avec l'instruction echo! Ça doit faire à peine 2 ou 3 ans que je sais qu'on peut lui passer plusieurs chaînes séparées par des virgules (donc inutile des les concaténer avec le point).
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  10. #10
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    octobre 2006
    Messages
    8 800
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : octobre 2006
    Messages : 8 800
    Points : 4 268
    Points
    4 268
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par CosmoKnacki Voir le message
    Ça m'est arrivé avec l'instruction echo! Ça doit faire à peine 2 ou 3 ans que je sais qu'on peut lui passer plusieurs chaînes séparées par des virgules (donc inutile des les concaténer avec le point).
    Je l'ai déjà lu (à mon avis, dans un post de DVP), mais l'avais oublié, et comme je ne vais pas l'utiliser dans les secondes qui viennent (j'ai vu à la télé tout à l'heure qu'il existait un nouveau métier : chasseur de maison et bien moi, j'exerce une activité pas nouvelle : chasseur de bugs ), ça va recommencer
    Il vaut mieux viser la perfection et la manquer que viser l'imperfection et l'atteindre. - Bertrand Russell

  11. #11
    Membre régulier Avatar de RowanMayfair
    Femme Profil pro
    Développeuse Freelance
    Inscrit en
    mars 2019
    Messages
    242
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : France, Haute Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Développeuse Freelance

    Informations forums :
    Inscription : mars 2019
    Messages : 242
    Points : 85
    Points
    85
    Par défaut
    Merci infiniment CosmoKnacki

    Là clairement ta solution c'était pas de mon niveau.

    Pour le foreach, en effet dans mes recherches j'avais cru comprendre que ça ne pouvait pas fonctionner, mais je n'avais pas compris pourquoi.

    Encore merci

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

Discussions similaires

  1. Supprimer une entrée d'une table sans casser les relations
    Par gvdmoort dans le forum Ruby on Rails
    Réponses: 4
    Dernier message: 05/10/2007, 13h02
  2. Réponses: 6
    Dernier message: 17/07/2007, 16h32
  3. [REG] Supprimer une entrée
    Par amirym dans le forum Scripts/Batch
    Réponses: 1
    Dernier message: 04/06/2007, 21h44
  4. Supprimer une entrée dans ajout suppression des programmes
    Par lavazavio dans le forum Windows XP
    Réponses: 5
    Dernier message: 01/05/2007, 18h30
  5. [Tableaux] Comment ajouter/supprimer une entrée d'un array
    Par dessinateurttuyen dans le forum Langage
    Réponses: 7
    Dernier message: 09/08/2006, 16h05

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