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

JavaScript Discussion :

Supprimer un élément d'un tableau 2D


Sujet :

JavaScript

  1. #1
    Membre du Club
    Homme Profil pro
    Reconverti Dev Web
    Inscrit en
    Septembre 2019
    Messages
    88
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Reconverti Dev Web
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Septembre 2019
    Messages : 88
    Points : 56
    Points
    56
    Par défaut Supprimer un élément d'un tableau 2D
    Bonjour,

    Est-il possible d'utiliser la méthode filter() pour filtrer un tableau 2D, le cas échéant quelles sont les alternatives?

    J'ai un tableau 2D contenant un objet dans chaque entrée, de ce genre :
    tab[0][0] = {status: 1}
    tab[0][1] = {status: 0}
    ...
    ...

    Mon but étant de supprimer de mon tableau tous les objets ayant le status = 0.

    Une idée pendant ce confinement du au Covid19?

    Cdt.

  2. #2
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 873
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 873
    Points : 3 717
    Points
    3 717
    Par défaut
    Salut,

    Il y a plusieurs façons de le faire...
    On peut utiliser la méthode filter mais voici une alternative :

    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    for (let line of tab) {
        for (let i = 0; i < line.length; i++) {
            if (line[i].status == 0) {
                line.splice(i, 1);
                i--;
            }
        }
    }

    Avec la méthode filter :

    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    for (let i = 0; i < tab.length; i++) {    
        tab[i] = tab[i].filter(elm => elm.status != 0);
    }

  3. #3
    Membre du Club
    Homme Profil pro
    Reconverti Dev Web
    Inscrit en
    Septembre 2019
    Messages
    88
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Reconverti Dev Web
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Septembre 2019
    Messages : 88
    Points : 56
    Points
    56
    Par défaut
    Merci, ta méthode avec le filter() marche parfaitement!


    Quelle est la méthode la plus rapide des 2?

    CDt

  4. #4
    Expert confirmé Avatar de psychadelic
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    2 529
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 2 529
    Points : 4 740
    Points
    4 740
    Par défaut
    La méthode filter ne supprime pas les éléments d'un tableau, elle crée un nouveau tableau avec les valeurs validée par le filtre. ( qui ici écrase l'ancien sous-tableau)


    sinon la méthode splice est la plus rapide, pour peu qu'on décrémente le compteur à chaque pas, ce qui évite d'avoir à le re décrémenter à chaque élément supprimé.

    vous pouvez tester par vous même
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    const tAstr = JSON.stringify( Array.from({length: 100},()=>({status:Math.floor(Math.random() *5)})) )
      ,   test1 = Array.from({length: 1000},()=>JSON.parse(tAstr))
      ,   test2 = Array.from({length: 1000},()=>JSON.parse(tAstr))
      ;
    console.time('filter')
    for (let i = 0; i < test1.length; i++) {    
      test1[i] = test1[i].filter(elm => elm.status != 0);
    }
    console.timeEnd('filter')  
     
    console.time('slice')
    for(let line of test2) {
      for(let i=line.length;i--;) {if (line[i].status===0) line.splice(i, 1)}
    }
    console.timeEnd('slice')
    «La pluralité des voix n'est pas une preuve, pour les vérités malaisées à découvrir, tant il est bien plus vraisemblable qu'un homme seul les ait rencontrées que tout un peuple.» [ René Descartes ] - Discours de la méthode

  5. #5
    Membre du Club
    Homme Profil pro
    Reconverti Dev Web
    Inscrit en
    Septembre 2019
    Messages
    88
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Reconverti Dev Web
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Septembre 2019
    Messages : 88
    Points : 56
    Points
    56
    Par défaut
    Merci, je ne connaissais pas console.time(), c'est très pratique

    Dernière question, comment connaitre la taille d'un tableau en 2D.

    Car après avoir filtrer tous mes éléments avec status == 0, la taille du tableau quant à elle n’évolue pas (uniquement le sous-tableau).

    Je voudrais connaitre combien d'elements à status == 1 restant dans le tableau, et si celui-ci est 0 appliquer une action.

    Existe t il une methode autre que mettre un compteur, et compter combien il y a d’élément ligne par ligne avec des boucles for?

  6. #6
    Expert confirmé
    Avatar de javatwister
    Homme Profil pro
    danseur
    Inscrit en
    Août 2003
    Messages
    3 681
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : danseur

    Informations forums :
    Inscription : Août 2003
    Messages : 3 681
    Points : 5 221
    Points
    5 221
    Par défaut
    Attention au lapsus classique: "slice" n'est pas "splice".

  7. #7
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 873
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 873
    Points : 3 717
    Points
    3 717
    Par défaut
    Salut,

    Citation Envoyé par psychadelic
    ... pour peu qu'on décrémente le compteur à chaque pas, ce qui èvite d'avoir à le re décrémenter à chaque élément supprimé.
    Oui bien vu.

    Citation Envoyé par nadfri2019
    Existe t il une methode autre que mettre un compteur, et compter combien il y a d’élément ligne par ligne avec des boucles for?
    Pas à ma connaissance mais c'est à vérifier...

    Mais pourquoi cherches-tu une autre méthode ? As-tu besoin de gagner du temps ?
    Si oui il y a peut-être moyen d'ajouter ce calcul de taille dans le code qui supprime tous les éléments de status égal à zéro...

    Citation Envoyé par nadfri2019
    Je voudrais connaitre combien d'elements à status == 1 restant dans le tableau, et si celui-ci est 0 appliquer une action.
    Je suppose qu'on a seulement deux cas (statut égal à 0 ou à 1) si oui pas besoin de savoir combien d'éléments à status == 1 il reste, non ? Puisque ce que tu veux c'est savoir si il en reste 0 ou pas...

    Si je fais cette nuance c'est parce que je pense que c'est plus rapide de savoir si il en reste 0 ou pas...

    Oui car il suffit de trouver un seul sous-tableau qui ait une taille différente de 0 pour répondre à la question (pas besoin de connaitre la taille des autres sous-tableaux...)

  8. #8
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    16 959
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 16 959
    Points : 44 122
    Points
    44 122
    Par défaut
    Bonjour,
    Citation Envoyé par psychadelic
    sinon la méthode slice est la plus rapide, (...)
    cela dépend de plein de choses et je n'obtiens pas les mêmes résultats que toi et chez moi slice est à la peine sur Chrome et fait jeu égal sous FireFox.

    Citation Envoyé par nadfri2019
    Existe t il une methode autre que mettre un compteur, et compter combien il y a d’élément ligne par ligne avec des boucles for?
    Si ton besoin est d'avoir un aperçu global et non « ligne par ligne » tu peux utiliser la méthode Array.flat(prof) en mettant une prof à 1, cela crée un Array et il te suffit de regarder sa longueur.

    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    const tab = [
     [{status:1},{status:0},{status:1},{status:0},{status:1}],
     [{status:0},{status:1},{status:0},{status:1},{status:0}],
     [{status:1},{status:0},{status:1},{status:0},{status:1}],
    ] 
    tab.forEach((el, ind) => {
      tab[ind] = el.filter((o) => o.status != 0);
    });
     
    console.log(tab.flat(1));
    Nota : au passage il est intéressant de constater que le forEach associé à filter est au moins aussi sinon plus performant que les méthodes déjà testées, enfin sur mon équipement.

  9. #9
    Membre du Club
    Homme Profil pro
    Reconverti Dev Web
    Inscrit en
    Septembre 2019
    Messages
    88
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Reconverti Dev Web
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Septembre 2019
    Messages : 88
    Points : 56
    Points
    56
    Par défaut
    Merci pour toutes vos réponses, la methode flat() est super intéressante.

    En fait voici ce que je cherche à faire:

    Je suis entrain de programmer un casse-brique, de ce fait j'utilise un tableau 2D afin d'avoir une grille pour localiser mes briques.
    -tab[0][0] correspond donc à la 1ere brique en haut à gauche.

    A l'heure actuelle, quand une brique est touchée, son statut passe de 1 à 0( n'ayant pas trouvé comment supprimer proprement l’élément du tableau).
    La fonction qui actualise les briques, fait en sorte de ne plus les dessiner.
    Quand tout est à 0, on a gagné le jeu vu qu'il ne reste plus de brique.

    Le problème actuel, c'est que les entrées du tableau sont toujours là, donc tout est recalculé à chaque itération.

    Je cherche donc un moyen, de réduire la taille du tableau au fur et à mesure de la disparition des briques jusqu'à que le tableau soit vide, entraînant la fin de la partie.
    Ceci afin d'optimiser le jeu et réduire le nombre de ligne de code.

    Voila à quoi ressemble mon programme à l'heure actuelle:
    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
     
    function updateNumberOfBricks()
    {
        for(let line of tabBricks) //Count of bricks destroyed
            for (let brick of line) 
              if (brick.status == 0) count--;
    }
     
    function updateDrawBricks()
    {      
        for(let line of tabBricks)  //Draw rest of bricks
            for (let brick of line)
                if (brick.status > 0 )
                    brick.drawRect();     
    }
     
    if (count == 0)  victory();

  10. #10
    Expert confirmé
    Avatar de javatwister
    Homme Profil pro
    danseur
    Inscrit en
    Août 2003
    Messages
    3 681
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : danseur

    Informations forums :
    Inscription : Août 2003
    Messages : 3 681
    Points : 5 221
    Points
    5 221
    Par défaut
    Franchement, je pense que ton tableau "2D" est peut-être une coquetterie. Si ta brique est touchée, tu l'élimines avec un splice et voilà...

  11. #11
    Expert confirmé Avatar de psychadelic
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    2 529
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 2 529
    Points : 4 740
    Points
    4 740
    Par défaut
    Citation Envoyé par nadfri2019 Voir le message
    Je suis entrain de programmer un casse-brique, de ce fait j'utilise un tableau 2D afin d'avoir une grille pour localiser mes briques.
    -tab[0][0] correspond donc à la 1ere brique en haut à gauche.
    pas besoin de mettre en oeuvre un tableau 2d pour ça faut juste coller le status sur chaque brique comme une classe et apres utiliser un querySelectorAll pour retrouver les briques
    «La pluralité des voix n'est pas une preuve, pour les vérités malaisées à découvrir, tant il est bien plus vraisemblable qu'un homme seul les ait rencontrées que tout un peuple.» [ René Descartes ] - Discours de la méthode

  12. #12
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    16 959
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 16 959
    Points : 44 122
    Points
    44 122
    Par défaut
    Je soupçonne un travail au travers d'un élément <canvas> dixit cette ligne
    dans ce cas l'usage d'un tableau de tableau n'est pas déconnante et correspond à « ligne/colonne ».

    Par contre pourquoi ne pas gérer le compteur dans la boucle du reDraw directement ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function updateDrawBricks() {
      let count = 0;
      for (let line of tabBricks) { //Draw rest of bricks
        for (let brick of line) {
          if (brick.status > 0) {
            brick.drawRect();
            count += 1;
          }
        }
      }
      return count;
    }
    Peut-être qu'un autre type de gestion sur base d'un Array d'objet serait plus lisible
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    const brique = {
      "posX": 0,      // la colonne
      "posY": 0,      // la ligne
      "statut": 1     // inutile si objet supprimé
    }

  13. #13
    Expert confirmé
    Avatar de javatwister
    Homme Profil pro
    danseur
    Inscrit en
    Août 2003
    Messages
    3 681
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : danseur

    Informations forums :
    Inscription : Août 2003
    Messages : 3 681
    Points : 5 221
    Points
    5 221
    Par défaut
    En fait, une simple variable décrémentée suffit pour savoir si tu as "tout cassé";

    Exemple bidon bidon: quand tu cliques une des 32 briques, elle disparaît et le compteur enregistre le changement. Si tu es à zéro, tu déclenches ce que tu veux.

    http://javatwist.imingo.net/cassebrique.htm

    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    const pl=document.querySelectorAll("#plateau > div > div");
    let tot=pl.length;
    pl.forEach(v => {
    	v.addEventListener("click",() => {
    		v.classList.add("hide");
    		tot--;
    		document.getElementById("check").textContent="briques restantes : " + tot;
    		if(tot==0){
    			document.getElementById("check").textContent="You win!"
    		}
    	})
    })

    Code css : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #plateau{text-align:center}
    #plateau div div{width:50px;height:20px;background-color:cyan;border:solid 1px lime;display:inline-block}
    .hide{visibility:hidden}

  14. #14
    Expert confirmé
    Avatar de javatwister
    Homme Profil pro
    danseur
    Inscrit en
    Août 2003
    Messages
    3 681
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : danseur

    Informations forums :
    Inscription : Août 2003
    Messages : 3 681
    Points : 5 221
    Points
    5 221
    Par défaut
    Citation Envoyé par NoSmoking Voir le message
    Peut-être qu'un autre type de gestion sur base d'un Array d'objet serait plus lisible
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    const brique = {
      "posX": 0,      // la colonne
      "posY": 0,      // la ligne
      "statut": 1     // inutile si objet supprimé
    }
    je pense aussi, sans nécessité d'éliminer physiquement un élément du tableau;
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    const pl=document.querySelectorAll("#plateau > div > div"),// briques html
    bricks=[];// tableau des briques
    pl.forEach((v,i) => {
    	bricks[i]={"status":true,"force":"chose","couleur":"truc","etc":false};
    	v.addEventListener("destroyed",() => {
    		v.classList.add("hide");
    		bricks[i].status=false;
    		// plus de status à true = victoire
    		if(bricks.some(one => one.status)){
    			// continuer à jouer
    		}
    		else console.log("gagné")
    	})
    })

  15. #15
    Membre du Club
    Homme Profil pro
    Reconverti Dev Web
    Inscrit en
    Septembre 2019
    Messages
    88
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Reconverti Dev Web
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Septembre 2019
    Messages : 88
    Points : 56
    Points
    56
    Par défaut
    En effet, c'est un casse brick en canvas:

    Ma brique est donc un objet de la classe appeler Shape, me servant aussi pour la balle:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    const bricks  = new Shape(10,10,50,20,"orange"); //(posX,posY,l,h,color)
    Voici comment sont créées mes briques par exemple:
    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
    const nLine      = 10; // number of lines
    const nCol       = 5; // number of columns
     
    function createBricks(tab)
    {
        for(let line = 0; line<nLine; line++) //number of lines
        {
            tab[line] = []; //create array of array
     
            for (let col=0; col<nCol; col++) //number of columns
            {	
                tab[line][col]        = Object.create(bricks); //each array is a brick objet
                tab[line][col].posX   = bricks.posX + (bricks.l)*col;
                tab[line][col].posY   = bricks.posY + (bricks.h)*line;
                tab[line][col].status = 1; 
            }
        }
    En fonction des niveaux, status peut-etre supérieur à 1, par exemple une brique ou il faut la toucher plusieurs fois pour la casser.

    La methode drawBrick(), sert juste à dessiner la brique dans le canvas.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
        drawRect()
        {
            ctx.beginPath();
            ctx.rect(this.posX,this.posY,this.l,this.h);
            ctx.fillStyle = this.color;
            ctx.fill();
        }
    Le tout est rafraichi avec le mouvement de la balle et la gestion des collisions via requestAnimationFrame().

    Donc il y a un grand nombre calcul par seconde, je voudrais donc eviter de faire des calculs inutile pour des briques qui ne s'affiche plus à l'ecran mais toujours presentes dans le tableau.

    Parcontre NoSmoking, c'est une bonne idée de mettre le count directement dans la fonction updateDrawBricks().
    J'economise une boucle, c'est déjà ça de gagné

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    function updateDrawBricks()
    {      
        for(let line of tabBricks)  //Draw rest of bricks
            for (let brick of line)
                if (brick.status > 0 )
                {
                    brick.drawRect();
                    count++;
                }

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

Discussions similaires

  1. Réponses: 4
    Dernier message: 07/05/2009, 13h50
  2. Supprimer certains éléments d'un tableau
    Par Him dans le forum Langage
    Réponses: 7
    Dernier message: 29/10/2008, 01h56
  3. [Tableaux] supprimer un élément d'un tableau
    Par banzzai dans le forum Langage
    Réponses: 1
    Dernier message: 15/09/2006, 15h52
  4. Réponses: 2
    Dernier message: 27/05/2006, 19h08
  5. Supprimer un élément d'un tableau
    Par CaptainChoc dans le forum Langage
    Réponses: 15
    Dernier message: 23/12/2002, 23h14

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