Je cherche à fusionner / combiner des objets dans un tableau chacun avec une série de tableaux imbriqués. Je veux fusionner les objets en fonction d'une clé spécifique (ici label[1]). Je peux utiliser Lodash et unionBy pour filtrer les doublons par label[1], mais comment puis-je conserver les valeurs des éléments filtrés?

Le tableau peut ressembler à ceci:

var arr = [{
    "label": ['item', 'private'],
    "values": [1, 2, 3]
  },
  {
    "label": ['item', 'private'],
    "values": [1, 2, 3, 6]
  },
  {
    "label": ['item', 'work'],
    "values": [1, 2, 8, 9]
  },
  {
    "label": ['item', 'private'],
    "values": [1, 2, 4, 5]
  },
  {
    "label": ['item', 'school'],
    "values": [1, 2, 7]
  }
];

Et la sortie souhaitée est:

var arr = [{
  "label": ["item", "private"],
  "values": [1, 2, 3, 4, 5, 6 ]
}, {
  "label": ["item", "work"],
  "values": [1, 2, 8, 9]
}, {
  "label": ["item", "school"],
  "values": [1, 2, 7]
}]

Voici un échantillon qui n'est qu'à mi-chemin.

var arr = [
  { label: ['item','private'], values: [1,2,3] },
  { label: ['item','private'], values: [1,2,3,6] },
  { label: ['item','work'], values: [1,2,8,9] },
  { label: ['item','private'], values: [1,2,4,5] },
  { label: ['item','school'], values: [1,2,7] }
];

var result = _.unionBy(arr, "label[1]");

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

Des idées?

Merci Lasse

0
Lasse van den Bosch Christense 20 nov. 2018 à 17:52

3 réponses

Meilleure réponse

Je ne sais pas comment faire cela avec lodash, mais je ne pense pas que unionBy soit la méthode pour le faire de toute façon.

Voici comment vous pouvez regrouper par étiquette à l'aide de lodash, puis réduire les groupes en une seule valeur pour fusionner les éléments d'un groupe.

const arr = [{"label":["item","private"],"values":[1,2,3]},{"label":["item","private"],"values":[1,2,3,6]},{"label":["item","work"],"values":[1,2,8,9]},{"label":["item","private"],"values":[1,2,4,5]},{"label":["item","school"],"values":[1,2,7]}];

console.log(
  Object.values(
    _.groupBy(arr, (item) => item.label.join()),//use lodash group by
  ).map((
    group, //now we have array of array of groups
  ) =>
    group
      .reduce((result, item) => ({
        //reduce a group to one object
        label: result.label, //set label
        values: [
          //set values with unique values of all items
          ...new Set(
            (result.values || []).concat(item.values || []),
          ),
        ],
      })),
  ),
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
0
HMR 20 nov. 2018 à 15:52

J'écrirais:

const arr2 = _(arr)
    .groupBy("label")
    .map(objs => ({
        label: objs[0].label,
        values: _(objs).flatMap("values").uniq().value(),
    }))
    .value()
2
tokland 20 nov. 2018 à 21:59

Vous pouvez également faire quelque chose comme ça via lodash :

var arr = [{ "label": ['item', 'private'], "values": [1, 2, 3] }, { "label": ['item', 'private'], "values": [1, 2, 3, 6] }, { "label": ['item', 'work'], "values": [1, 2, 8, 9] }, { "label": ['item', 'private'], "values": [1, 2, 4, 5] }, { "label": ['item', 'school'], "values": [1, 2, 7] } ]

const merge = arr => _.reduce(arr, (r,c) => _.union(r, c.values), [])
const result = _(arr).groupBy('label')
 .entries()
 .reduce((r,[k,v]) => (r.push({ label: k.split(','), values: merge(v) }), r), [])

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>

L'idée est de regrouper d'abord via _.groupBy puis d'obtenir les entrées (via _.entries) afin que vous puissiez former la sortie souhaitée via _.reduce. _.union nous utilisons pour fusionner les tableaux de valeurs dans le cadre de la reduce finale.

Voici l'implémentation ES6 :

var arr = [{ "label": ['item', 'private'], "values": [1, 2, 3] }, { "label": ['item', 'private'], "values": [1, 2, 3, 6] }, { "label": ['item', 'work'], "values": [1, 2, 8, 9] }, { "label": ['item', 'private'], "values": [1, 2, 4, 5] }, { "label": ['item', 'school'], "values": [1, 2, 7] } ]

const mrg = arr => Array.from(new Set(arr.reduce((r,c) => [...r, ...c.values], [])))
const grp = (arr, k) => arr.reduce((r,c) => (r[c[k]] = [...r[c[k]] || [], c], r), {}) 
const result = Object.entries(grp(arr, 'label'))
  .reduce((r,[k,v]) => (r.push({ label: k.split(','), values: mrg(v) }), r), [])

console.log(result)
0
Akrion 20 nov. 2018 à 17:51