【问题标题】:javascript find object by same keys and merge themjavascript通过相同的键查找对象并将它们合并
【发布时间】:2019-06-16 09:45:59
【问题描述】:

所以我有一个对象数组,我创建了两个字典来映射名称。 我想找到所有具有相同键的对象并将它们合并。还要连接该值。 这是我所做的,但卡住了:

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();

我认为删除重复项时我做错了? 接下来我该怎么做?

为了解释我想要什么,将显示我想要的数组:

对象的初始数组:

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

对象的结果数组:

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

【问题讨论】:

  • 添加示例中 wordcloudData 应创建的最终结果示例?
  • @OriDrori 谢谢,我已经添加了
  • 你会接受不使用 lodash 的答案吗?如果在合并时所有项目都具有不同的值,那么颜色的最终值是多少?
  • 是的,我会接受不使用 lodash 的答案,映射项目的颜色值将相同,原因之一是我没有在最终结果中指出为数组着色

标签: javascript arrays object ecmascript-6 lodash


【解决方案1】:

使用_.mergeWith()并根据key选择如何组合值:

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);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

【讨论】:

  • 非常感谢!我会坚持你的选择
【解决方案2】:

这里有一个没有lodash 并使用reduce() 的版本:

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);

【讨论】:

    【解决方案3】:

    这是一个使用纯 ES6 的简短解决方案,并将合并逻辑分离到自己的函数中: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)
    

    希望对您有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-30
      • 2014-12-27
      • 2020-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多