1
votes

Comment regrouper des tableaux dans un tableau par clé d'objet du premier élément

Vous avez un tableau de tableaux comme celui-ci:

let final = []
  for (let i=0; i<arr.length; i++) {

    let arr1 = i==0?arr:arr.slice(i)

    let final1 = arr1.reduce((acc,x)=> {

      acc = acc[0].key==x[0].key?acc.concat(x):acc
      return acc
    })
    arr1.length>1&&final.push(final1)
  }

Je dois obtenir ce arr mais avec des tableaux groupés avec la même valeur "clé" du premier élément donc ça ressemblera à:

  let arr = [
      [
        {"key":2, "other":123},
        {"key":2, "other":222}
      ],
      [
        {"key":3, "other":0}
      ],
      [
        [
          {"key":1, "other":11},
          {"key":1, "other":23}
        ],
        [
          {"key":1, "other":22}
        ]
      ],

    ]

J'ai essayé d'utiliser la fonction de réduction, mais le résultat était totalement différent.

    let arr = [
      [
        {"key":2, "other":123},
        {"key":2, "other":222}
      ],
      [
        {"key":3, "other":0}
      ],
      [
        {"key":1, "other":11},
        {"key":1, "other":23}
      ],
      [
        {"key":1, "other":22}
      ]
    ]

Dans ce code, le problème est qu'il compare arr [1] avec arr [2], arr [3] puis à nouveau arr [2] avec arr [3] et le regroupe (même si arr [1] .key et arr [2] .key et arr [3] .key sont identiques) Pouvez-vous donner quelques conseils ou donner la fonction finale pour faire cela?

p>


5 commentaires

Pourquoi avez-vous choisi cette structure? Quel est le cas d'utilisation derrière cela? Cela ressemble à un problème XY.


2 tableaux où les objets ont la même valeur de clé sont regroupés en tableau: [tableau, tableau]


c'est un jeu de données étrange, je ne peux prévoir aucun avantage d'une telle structure, ni pour les performances, ni pour la lisibilité.


Oui je vois ça. mais pourquoi? Pourquoi pas [{key: 1, count: 2}, ...] ?


J'obtiens une réponse JSON de l'API et je dois la regrouper pour qu'elle s'affiche en blocs. La structure du tableau initial est le résultat d'un regroupement de premier niveau, et la tâche est la deuxième afin de les lister en divs comme j'ai besoin


4 Réponses :


0
votes

Je pense que vous voulez quelque chose comme ça, essayez d'exécuter l'extrait de code

let arr = [
    [
        {
            "key": 2
        },
        {
            "key": 2
        }
    ],
    [
        {
            "key": 3
        }
    ],
    [
        {
            "key": 1
        },
        {
            "key": 1
        }
    ],
    [
        {
            "key": 1
        }
    ]
]


let result = arr.reduce((res, array) => {
    array.forEach((value, index) => {
        const obj = res.find(a => {
            return !!a.find(({key}) => {
                return key === value.key
            })
        })
        if (obj) {
            obj.push(value)
        } else {
            res.push([value])
        }
    })
    return res;
}, [])


console.log(result);


0 commentaires

1
votes

Créez l'objet de clés avec son décompte. Ensuite, vous pouvez filtrer les clés qui sont présentes plusieurs fois i: e (count> = 2) . Ensuite, parcourez votre tableau d'entrée en utilisant reduction et voyez qu'il est présent dans les clés du tableau filtré, si oui, insérez un tableau séparé et l'autre est accu . Ensuite, fusionnez les deux tableaux en un seul.

let input = [
    [
      {"key":2, "other":123},
      {"key":2, "other":222}
    ],
    [
      {"key":3, "other":0}
    ],
    [
      {"key":1, "other":11},
      {"key":1, "other":23}
    ],
    [
      {"key":1, "other":22}
    ]
];

// keys with unique key and its count. filter whose count are greater than two.

const groupByArrKeysOccurence = input.reduce((accu, arr) => {
    const key = arr[0].key;
    accu[key] = (accu[key] || 0) + 1;
    return accu;
}, {});

const filteredKeys = Object.entries(groupByArrKeysOccurence).filter(([_, val]) => val > 1).map(([key, _]) => Number(key));

const multipleArrOccurenceKeys = [];

const singleArrOccurenceKeys = input.reduce((accu, arr) => {
    const isKey = arr.some(({key}) => filteredKeys.includes(key));
    if(isKey) {
        multipleArrOccurenceKeys.push(arr);
    } else {
        accu.push(arr);
    }
    return accu;
}, []);

console.log([...singleArrOccurenceKeys, multipleArrOccurenceKeys]);


1 commentaires

Cela fonctionne avec l'exemple, cependant si nous modifions le premier tableau du tableau d'entrée de [{"key": 2, "other": 123}, {"key": 2, "other": 222}] à [{"key ": 3," other ": 123}, {" key ": 3," other ": 222}], la longueur finale du tableau doit être 2, le premier tableau avec key = 3 et le second avec key = 1



0
votes

Cette solution ne produit pas le résultat exact que vous recherchez, mais elle est agréable et propre. Le résultat souhaité vous posera très probablement des problèmes à l'avenir, car certains éléments sont davantage imbriqués que d'autres.

Cette réponse suppose que chaque tableau a toujours au moins un élément, car la question est de regrouper par le clé du premier élément.

let arr = [[{"key":2, "other":123}, {"key":2, "other":222}], [{"key":3, "other":0}], [{"key":1, "other":11}, {"key":1, "other":23}], [{"key":1, "other":22}]];

let groups = {};
let group = key => groups[key] || (groups[key] = []);
arr.forEach(arr => group(arr[0].key).push(arr));

console.log(groups);
console.log(Object.values(groups));

// If you want to get the result you're looking for (not looking at the
// order), you can simply flatten all groups of 1 element. Although
// depending on your use case I recommend sticking with the above.

console.log(Object.values(groups).map(group => group.length === 1 ? group[0] : group));


0 commentaires

1
votes
let arr = [
      [
        {"key":2},
        {"key":2}
      ],
      [
        {"key":3}
      ],
      [
        {"key":1},
        {"key":1}
      ],
      [
        {"key":1}
      ]
    ]
var myMap = new Map();
for (i = 0; i < arr.length; i++) { 
    if(!myMap.has(arr[i][0]['key'])){
        myMap.set(arr[i][0]['key'],i)
    }else if(myMap.get(arr[i][0]['key'])===undefined){

        myMap.set(arr[i][0]['key'],i)
    }else{
        myMap.set(arr[i][0]['key'],myMap.get(arr[i][0]['key'])+','+i)
    }
}
var out =[];
for(var v of myMap.values()){
    var s = String(v).split(",");
    var fi = s[0]
    var subarray =[]
    for(var i in s){
        subarray.push(arr[s[i]]) 
    }
    out[fi] = subarray;
}
You will find your response in out array. Hope that it works for you

0 commentaires