简体   繁体   English

使用lodash或ramda变换对象数组

[英]Transform array of objects using lodash or ramda

This is the data structure that I got after doing query database. 这是查询数据库后获得的数据结构。

[
    { name: 'xx1', date: '2017-09-03', value: 49 },
    { name: 'xx2', date: '2017-10-23', value: 67 },
    { name: 'xx2', date: '2017-12-01', value: 70 },
    ...
]

I want to transform it into: 我想将其转换为:

[
    { name: 'xx1', data: { '2017-09-03': 49 } },
    { name: 'xx2', data: { '2017-10-23': 67, '2017-12-01': 70 } },
    ...
]

That data structure is needed in order to build chart using react-chartkick . 为了使用react-chartkick构建图表,需要该数据结构。

Can anyone give me suggestion to solve this? 谁能给我建议解决这个问题? (Especially with lodash or ramda) (尤其是lodash或ramda)

I would use following approach based on reduce and find (ES6) methods: 我将基于reducefind (ES6)方法使用以下方法:

const data = [
  { name: 'xx1', date: '2017-09-03', value: 49 },
  { name: 'xx2', date: '2017-10-23', value: 67 },
  { name: 'xx2', date: '2017-12-01', value: 70 }
];

const result = data.reduce((acc, item) => {
  const found = acc.find(a => a.name === item.name);
  if (found) {
     found.data[item.date] = item.value;
  } else {
    acc.push({
      name: item.name,
      data: {
        [item.date]: item.value
      }
    });
  }
  return acc;
}, []);

If you don't want ES6, both methods have lodash versions: reduce , find . 如果您不希望使用ES6,则这两种方法都具有lodash版本: reducefind

You can accumulate an object with Array#reduce() and return its Object.values() : 您可以使用Array#reduce()累积对象并返回其Object.values()

 const data = [ { name: 'xx1', date: '2017-09-03', value: 49 }, { name: 'xx2', date: '2017-10-23', value: 67 }, { name: 'xx2', date: '2017-12-01', value: 70 } ] const map = data.reduce((acc, { name, date, value }) => { if (!(name in acc)) { acc[name] = { name, data: {} } } acc[name].data[date] = value return acc }, {}) const result = Object.values(map) console.log(result) 

This approach avoids using Array#find() which is O(n) time complexity and uses name in acc to check for existence and acc[name] for access, which are both O(1) time complexity, making this approach O(n) overall. 这种方法避免使用Array#find() ,它的时间复杂度为O(n),并且name in acc使用name in acc来检查是否存在,并且使用acc[name]进行访问,这两者都是O(1)的时间复杂度,因此该方法为O(n ) 总体。

In contrast, the other answer is O(n 2 ) time complexity overall. 相反, 另一个答案是总体的O(n 2 )时间复杂度。

For a solution using lodash, you can use its _.map , _.groupBy , and _.merge methods to accomplish this. 对于使用lodash的解决方案,可以使用其_.map_.groupBy_.merge方法来完成此任务。

I find it's easier to follow using the _.chain style, but you can easily convert it to a normal set of nested calls if you like. 我发现使用_.chain样式更容易_.chain ,但是您可以根据需要轻松地将其转换为一组普通的嵌套调用。

 const data = [ { name: 'xx1', date: '2017-09-03', value: 49 }, { name: 'xx2', date: '2017-10-23', value: 67 }, { name: 'xx2', date: '2017-12-01', value: 70 }, ] const result = _.chain(data) .map(val => ({name: val.name, data: {[val.date]: val.value}})) // convert objects to desired format .groupBy("name") // group objects by name .map(v => _.merge(...v)) // merge objects in each group .value(); // done! console.log(result); 
 <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.10/lodash.min.js"></script> 

Ramda's R.reduceBy or R.groupBy can help you here. R.reduceByR.reduceByR.groupBy可以在这里为您提供帮助。 In the example below R.reduceBy groups the objects in the array by their name property and then combines the grouped elements by building up the new object with R.assoc . 在下面的示例中, R.reduceBy通过name属性对数组中的对象进行分组,然后通过使用R.assoc建立新对象来组合分组的元素。 The remaining combination of R.toPairs , R.map and R.zipObj will get the result into the shape you want. R.toPairsR.mapR.zipObj的其余组合将结果转换为所需的形状。

 const fn = R.pipe( R.reduceBy((res, {date, value}) => R.assoc(date, value, res), {}, R.prop('name')), R.toPairs, R.map(R.zipObj(['name', 'data'])) ) const data = [ { name: 'xx1', date: '2017-09-03', value: 49 }, { name: 'xx2', date: '2017-10-23', value: 67 }, { name: 'xx2', date: '2017-12-01', value: 70 } ] console.log(fn(data)) 
 <script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM