1
votes

javascript trouver un objet avec les mêmes clés et les fusionner

J'ai donc un tableau d'objets, j'ai créé deux dictionnaires pour mapper les noms. Je veux trouver tous les objets avec la même clé et les fusionner. Concaténez également ces valeurs. Voici ce que j'ai fait, mais bloqué:

{ name: 'nice', weight: 6, color: 1, reviews: [ '161', '329', '111', '131', '211', '499'] },
{ name: 'great', weight: 4, color: 1, reviews: [ '18', '19' ] } 

Je pense que je fais mal lors de la suppression des doublons? Que dois-je faire ensuite?

Pour expliquer ce que je veux, montrera quel tableau je veux qu'il soit:

Tableau initial d'objet: p>

{
 'pretty cool': [3, 1, ['161', '329']],
 'pretty damn': [2, 1, ['111', '131']],
 'pretty nice': [1, 1, ['211', '499']],
 'great': [4, 1, ['18', '19']],
}; 

Tableau d'objets de résultat:

const wordcloudData = {
  'pretty cool': [3, 1, ['161', '329']],
  'pretty damn': [2, 1, ['111', '131']],
  'pretty nice': [1, 1, ['211', '499']],
  'great': [4, 1, ['18', '19']],
};

const dict = {
  'pretty cool': 1, 
  'pretty damn': 1,
  'pretty nice': 1,
};

const dictNames = {
  1: 'nice',
}


const formattedArray = _
  .chain(wordcloudData)
  .keys()
  .map(item => {
    const [weight, color, reviews] = wordcloudData[item];

    return {
      name: dictNames[dict[item]] || item,
      weight: weight,
      color: color,
      reviews: reviews,
    }
  })
  /* Here i'm getting that type of array:
   [ 
    { name: 'nice', weight: 1, color: 1, reviews: [ '211', '499' ] },
    { name: 'nice', weight: 2, color: 1, reviews: [ '111', '131' ] },
    { name: 'nice', weight: 3, color: 1, reviews: [ '161', '329' ] },
    { name: 'great', weight: 4, color: 1, reviews: [ '18', '19' ] } 
   ]
  */
  .groupBy('name')
  .map(_.spread(_.assign)) // Here i'm trying to get rid of objects with same key, but something goes wrong
  .value();


4 commentaires

Ajouter un exemple du résultat final du que le wordcloudData dans l'exemple devrait créer?


@OriDrori merci, j'ai ajouté


Accepteriez-vous une réponse sans utiliser de lodash? Quelle serait également la valeur finale de la couleur si tous les éléments avaient des valeurs différentes lorsque vous les fusionnez?


oui, j'accepterai la réponse sans utiliser de lodash, les valeurs de couleur seront les mêmes pour les éléments de mappage, l'une des raisons, je ne suis pas pointé dans le résultat final pour colorer un tableau


3 Réponses :


1
votes

Utilisez _.mergeWith () et choisissez comment combiner les valeurs en fonction de la clé:

<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
const wordcloudData = {
  'pretty cool': [3, 1, ['161', '329']],
  'pretty damn': [2, 1, ['111', '131']],
  'pretty nice': [1, 1, ['211', '499']],
  'great': [4, 1, ['18', '19']],
};

const dict = {
  'pretty cool': 1, 
  'pretty damn': 1,
  'pretty nice': 1,
};

const dictNames = {
  1: 'nice',
}

const merger = _.partial(_.invoke, {
  weight: _.add,
  reviews: _.concat,
});

const formattedArray = _(wordcloudData)
  .map(([weight, color, reviews], item) => ({
    name: _.get(dictNames, dict[item], item),
    weight,
    color,
    reviews
  }))
  .groupBy('name')
  .map(v => _.mergeWith(...v, (o, s, k) => merger(k, o, s)))
  .value();
  
console.log(formattedArray);


1 commentaires

Merci beaucoup! Je m'en tiendrai à ton choix



1
votes

Ici, vous avez une version sans lodash et utilisant réduire () :

const wordcloudData = {
  'pretty cool': [3, 1, ['161', '329']],
  'pretty damn': [2, 1, ['111', '131']],
  'pretty nice': [1, 1, ['211', '499']],
  'great': [4, 1, ['18', '19']],
};

const dict = {
  'pretty cool': 1, 
  'pretty damn': 1,
  'pretty nice': 1,
};

const dictNames = {
  1: 'nice',
}

let merged = Object.keys(wordcloudData).reduce((res, curr) =>
{
    let new_name = dictNames[dict[curr]] || curr;
    let [weigth, color, review] = wordcloudData[curr];
    let found = res.findIndex(x => x.name === new_name);
    
    if (found >= 0)
    {        
        res[found].weigth += weigth;
        res[found].color = color;
        res[found].review.push(...review);
    }
    else
    {
        res.push({
            name: new_name,
            weigth: weigth,
            color: color,
            review: review
        });
    }

    return res;

}, []);

console.log(merged);


0 commentaires

1
votes

Voici une courte solution utilisant ES6 standard et séparant la logique de fusion en sa propre fonction: https://jsbin.com/qevohugene/edit?js,console

const wordcloudData = {
  'pretty cool': [3, 1, ['161', '329']],
  'pretty damn': [2, 1, ['111', '131']],
  'pretty nice': [1, 1, ['211', '499']],
  'great': [4, 1, ['18', '19']],
};

const dict = {
  'pretty cool': 1, 
  'pretty damn': 1,
  'pretty nice': 1,
};

const dictNames = {
  1: 'nice',
}

const mergeItems = (oldItem, newItem) => ({
  name: newItem.name,
  weight: newItem.weight + oldItem.weight,
  color: newItem.color,
  reviews: [...oldItem.reviews, ...newItem.reviews]
});

const formattedArray = Object.entries(wordcloudData)
  .map(([key, [weight, color, reviews]]) => ({
      name: dictNames[dict[key]] || key,
      weight: weight,
      color: color,
      reviews: reviews,
    }))
  .reduce((accum, item) => {
    return accum.some(x => x.name === item.name)
      ? accum.map(x => x.name === item.name ? mergeItems(x, item) : x)
      : [...accum, item];
  }, []);
console.log(formattedArray)

J'espère que cela vous aidera.


0 commentaires