使用lodash处理地图、求和、平均值

huangapple go评论72阅读模式
英文:

Working with Map, Sum, mean using loadash

问题

// 背景
// 我有以下数据集
let animals =
[
  { id: 1, attributes: [{ title: 'cat', score: 3, weight: 30 }] },
  { id: 2, attributes: [{ title: 'cat', score: 4, weight: 22 }] },
  { id: 3, attributes: [{ title: 'dog', score: 5, weight: 26 }] },
  { id: 4, attributes: [{ title: 'dog', score: 5, weight: 22 }] }
]

// 我的要求是将其转换为以下形式
let animals =
[
  { animal: 'cat', avg_score: 3.5, avg_weight: 26 },
  { animal: 'dog', avg_score: 5, avg_weight: 24 }
]
// 其中 avg_score 和 avg_weight 应该是相应标题的分数和重量的平均值。

// 阅读 lodash 的文档后,我能够发现以下事项:
// 1. 我们需要使用 _.groupBy() 函数按标题分组
// 2. 我们需要使用 _mean() 函数来计算平均值

// 我无法弄清楚如何将这两者结合起来。我迄今为止尝试的方法如下:

const answer = _(animals)
  .groupBy('attributes.title')
  .map(() => ({
    title: attributes.title,
    score: _.mean(attribute.score),
    weight: _.mean(attribute.weight),
  }))
  .value();

console.log("主数据:" + answer);

// 但是,由于标题、分数和重量是子项,我们需要某种循环来迭代并获取相应行的实体。
// 例如,分配应该是类似 `title: row.attributes.title` 这样的东西,其中 row 是循环中来自迭代的引用。
// 有人能帮助解决这个问题吗?

你的代码存在一些语法错误和逻辑问题。我帮你做了修正,这里是修改后的代码:

// 导入 lodash 库
const _ = require('lodash');

// 数据集
let animals =
[
  { id: 1, attributes: [{ title: 'cat', score: 3, weight: 30 }] },
  { id: 2, attributes: [{ title: 'cat', score: 4, weight: 22 }] },
  { id: 3, attributes: [{ title: 'dog', score: 5, weight: 26 }] },
  { id: 4, attributes: [{ title: 'dog', score: 5, weight: 22 }] }
];

// 使用 lodash 来对数据进行转换
const transformedAnimals = _.chain(animals)
  .groupBy((animal) => animal.attributes[0].title)
  .map((groupedAnimals, animal) => {
    const avg_score = _.meanBy(groupedAnimals, (a) => a.attributes[0].score);
    const avg_weight = _.meanBy(groupedAnimals, (a) => a.attributes[0].weight);
    return { animal, avg_score, avg_weight };
  })
  .value();

// 打印转换后的数据
console.log(transformedAnimals);

这段代码修复了语法错误,并使用 lodash 函数来正确地对数据进行分组和计算平均值。

英文:

Background

I've the following data set with me

let animals = 
[
  {id:1, attributes:[{ title:'cat',score:3, weight:30 }]},
  {id:2, attributes:[{ title:'cat',score:4, weight:22 }]},
  {id:3, attributes:[{ title:'dog',score:5, weight:26 }]}
  {id:4, attributes:[{ title:'dog',score:5, weight:22 }]}

]

My requirement is to make this look like this:

let animals = 
[
  { animal:'cat',avg_score:3.5, avg_weight:26 },
  { animal:'dog',avg_score:5, avg_weight:24 } 
]

Where the avg_score and avg_weight should be the average of the score and weight for the respective title.

Reading the documentation of loadash, I was able to figure out that,

  1. We need to use _.groupBy() function to group by title
  2. we need to use _mean() function to take the average

I'm unable to figure out how to get this done together. What I tried so far-

	const answer = _( animals )
		.groupBy( 'attributes.title' )
		.map( () => ( {
			title: attributes.title,
                        score: _.mean(attribute.score),
                        weight: _.mean(attribute.weight),
		} ) )
		.value();

	console.log( "Master Data : " + answer );

However, since the title, score, and weight are child items and we need some kind of a loop to iterate and get the corresponding row's entity, i'm unable to process further. Example, the assignment should be something like 'title' : row.attributes.title where row is reference of the iteration coming form the loop.
Can someone please help out to unfold this?

答案1

得分: 3

使用普通的ES6:

对于每个动物条目,使用reduce来保持得分、重量和计数的累积总和。然后根据总和和计数来计算平均值。

const animals = [
  {"id": 1, "attributes": [{"title": "cat", "score": 3, "weight": 30}]},
  {"id": 2, "attributes": [{"title": "cat", "score": 4, "weight": 22}]},
  {"id": 3, "attributes": [{"title": "dog", "score": 5, "weight": 26}]},
  {"id": 4, "attributes": [{"title": "dog", "score": 5, "weight": 22}]
}];

const result = Object.values(animals.reduce((accumulator, {attributes: [{title, score, weight}]}) => {
  const entry = accumulator[title] ??= { animal: title, count: 0, totalScore: 0, totalWeight: 0 };
  entry.count++;
  entry.totalScore += score;
  entry.totalWeight += weight;
  return accumulator;
}, {})).map(({ animal, count, totalScore, totalWeight }) => ({
  animal,
  avg_score: totalScore / count,
  avg_weight: totalWeight / count
}));

console.log(result);

这段代码会计算每种动物的平均得分和平均重量。

英文:

With plain ES6:

For each animal entry, use reduce to keep a running total of score, weight, and count. Then calculate the averages as total/count.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const animals = [{&quot;id&quot;:1,&quot;attributes&quot;:[{&quot;title&quot;:&quot;cat&quot;,&quot;score&quot;:3,&quot;weight&quot;:30}]},{&quot;id&quot;:2,&quot;attributes&quot;:[{&quot;title&quot;:&quot;cat&quot;,&quot;score&quot;:4,&quot;weight&quot;:22}]},{&quot;id&quot;:3,&quot;attributes&quot;:[{&quot;title&quot;:&quot;dog&quot;,&quot;score&quot;:5,&quot;weight&quot;:26}]},{&quot;id&quot;:4,&quot;attributes&quot;:[{&quot;title&quot;:&quot;dog&quot;,&quot;score&quot;:5,&quot;weight&quot;:22}]}]

const r = Object.values(animals.reduce((a,
  {attributes:[{title,score,weight}]},o)=&gt;(
    o=(a[title]??={animal:title, count:0, totalScore:0, totalWeight:0}),
    o.count++, o.totalScore+=score, o.totalWeight+=weight, a),{}))
  .map(({animal,count,totalScore,totalWeight})=&gt;
    ({animal, avg_score:totalScore/count, avg_weight:totalWeight/count}))

console.log(r)

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年2月24日 11:14:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/75552302.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定