6
votes

Javascript séparant le tableau d'objets en plusieurs tableaux à l'aide de map () et Iterator

  1. En gros, j'ai un tableau d'objets comme

    var array = [{x: 10, y: 5, r: 10, ...}]

  2. Il y a plus de champs dans l'objet, mais justement, c'est la façon dont j'ai trouvé pour séparer les champs en tableaux:

    var [x, y] = array.map(obj => [obj.x, obj.y]); // should output two arrays
    

    Fonctionne, mais semble très inefficace car le nombre de champs et la taille du tableau augmentent, car cela scanne le tableau plusieurs fois. Je pourrais utiliser une boucle standard, mais je préfère la carte () car je pense qu'elle est plus lisible dans ce cas. Est-il possible de renvoyer plusieurs valeurs de la carte? Je pense à quelque chose comme:

    var x = array.map(obj => obj.x);
    var y = array.map(obj => obj.y);
    // and so on for each field
    

    Ou quelque chose de similaire qui sera lisible (réduire est moins lisible IMO).

    1. J'ai remarqué des fonctions javascript plus récentes comme array.entries () qui renvoient un objet itérateur. Comment puis-je implémenter de telles fonctions?

1 commentaires

Tous les objets contiennent-ils les mêmes clés?


3 Réponses :


6
votes

Vous pouvez réduire le tableau et itérer les paires clé / valeur des objets. Ensuite, transmettez les valeurs au tableau de la propriété donnée.

.as-console-wrapper { max-height: 100% !important; top: 0; }
var array = [{ x: 10, y: 5, r: 10 }, { x: 11, y: 6, r: 11 }],
    result = array.reduce((r, o) => {
        Object.entries(o).forEach(([k, v]) => (r[k] = r[k] || []).push(v));
        return r;
    }, Object.create(null));
    
console.log(result);


0 commentaires

4
votes

Donc, vous étiez sur le bon départ avec votre deuxième tentative:

var [x, y] = array.reduce(
    (accum, val) => {
        accum[0].push(val.x);
        accum[1].push(val.y);
        return accum;
    },
    [ [], [] ]
);

Comme vous l'indiquez, la première tentative est trop inefficace, car vous devrez parcourir le tableau plusieurs fois pour chaque champ que vous souhaitez extraire, mais vous pouvez faire tout ce que vous voulez en utilisant la méthode .reduce () d'un tableau.

Je ferais ce qui suit: p >

var [x, y] = array.map(obj => [obj.x, obj.y]);

Ce que je fais, c'est dire au réducteur d'initialiser l'accumulateur avec un tableau vide de tableaux ( [[], []] ), et quand il boucle à travers le tableau, il mettra les propriétés .x dans le premier tableau de l'accumulateur et les propriétés .y dans le second tableau. Et grâce à la déstructuration, x sera un tableau de toutes les propriétés .x et y sera un tableau de tous les . y properties.

Cette approche est facile à étendre au fur et à mesure que vos champs se développent en ajoutant plus de tableaux vides à l'objet accumulateur initial et en vous assurant dans le réducteur de pousser ces champs dans ce nouvel objet.


1 commentaires

Comment le rendre générique? c'est-à-dire pas seulement pour deux propriétés



0
votes

Si tous les objets ont les mêmes clés, vous pouvez obtenir une copie de ces clés et du cache afin de ne pas avoir besoin de les obtenir pour chaque objet. Vous pouvez ensuite utiliser ces clés pour initialiser l'objet de résultat, puis boucler le tableau et pousser les valeurs dans les tableaux, comme ceci:

var array = [{ x: 10, y: 5, r: 10 }, { x: 11, y: 6, r: 11 }];

var keys = Object.keys(array[0]);
var result = {};

keys.forEach(key => result[key] = []);

array.forEach(obj =>
  keys.forEach(key => result[key].push(obj[key]))
);
    
console.log(result);

Démo: p >

var keys = Object.keys(array[0]);                          // get the keys of the first object (assuming all objects have the same keys)
var result = {};                                           // the result object (you can use the safe Object.create(null) instead of {})

keys.forEach(key => result[key] = []);                     // initialize the result object (make an empty array entry for each key in keys)

array.forEach(obj =>                                       // for each object in array
  keys.forEach(key => result[key].push(obj[key]))          // add the values of this object to their corresponding array from result using keys from the array keys
);


0 commentaires