JavaScript的Reduce如何分配其价值?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript的Reduce如何分配其价值?相关的知识,希望对你有一定的参考价值。
问题:我不明白reduce
是如何从阵列中分配/减少客户名称的。我需要有人来解释这里发生的事情。
详细说明
在Fun Fun Function的函数式编程系列(https://www.youtube.com/watch?v=1DMolJ2FrNY)的第4集中,Mattias Petter Johansson介绍了为客户及其订单加载简单数据集并通过reduce
函数将数据转换为分层对象的示例。
这是示例制表符分隔的数据集 - 我在本地命名为data.txt
。
mark johannson waffle iron 80 2
mark johannson blender 200 1
mark johannson knife 10 4
Nikita Smith waffle iron 80 1
Nikita Smith knife 10 2
Nikita Smith pot 20 3
这是加载和处理数据集的javascript文件 - 我在本地命名为reduce.js
。
var fs = require("fs");
var output = fs
.readFileSync("data.txt", "utf-8")
.trim()
// NOTE: On Windows, I needed to use
. You may only need
or
.
.split("
")
.map(line => line.split(" "))
.reduce((customers, line) => {
customers[line[0]] = customers[line[0]] || [];
customers[line[0]].push({
name: line[1],
price: line[2],
quantity: line[3]
});
return customers;
}, {});
console.log("output", JSON.stringify(output, null, 2));
最后,这是我用来通过NodeJS
执行这个js文件的简单命令。
node reduce.js
(或者,如果你想在一个地方看到所有代码和数据,我在这里包含了一个jsFiddle:https://jsfiddle.net/anthonygatlin/27vpoa13/)
代码执行的输出看起来像
{
"mark johannson": [
{
"name": "waffle iron",
"price": "80",
"quantity": "2"
},
{
"name": "blender",
"price": "200",
"quantity": "1"
},
{
"name": "knife",
"price": "10",
"quantity": "4"
}
],
"Nikita Smith": [
{
"name": "waffle iron",
"price": "80",
"quantity": "1"
},
{
"name": "knife",
"price": "10",
"quantity": "2"
},
{
"name": "pot",
"price": "20",
"quantity": "3"
}
]
}
让我们快速浏览一下代码中发生的事情。
.readFileSync("data.txt", "utf-8")
使用utf-8
编码读入文件。 (否则,文字难以理解。)
在utf-8
转换之前......
<Buffer 6d 61 72 6b 20 6a 6f 68 61 6e 6e 73 6f 6e 09 77 61 66 66 6c 65 20 69 72 6f 6e 09 38 30 09 32 0d 0a 6d 61 72 6b 20 6a 6f 68 61 6e 6e 73 6f 6e
09 62 6c ... >
在utf-8
转换之后......
mark johannson waffle iron 80 2
mark johannson blender 200 1
mark johannson knife 10 4
Nikita Smith waffle iron 80 1
Nikita Smith knife 10 2
Nikita Smith pot 20 3
.trim()
函数删除文件末尾的任何换行符。.split(" ")
和.map(line => line.split(" "))
函数将传入的文件文本转换为数组数组。
在.split("
")
之后
[ 'mark johannson waffle iron 80 2',
'mark johannson blender 200 1',
'mark johannson knife 10 4',
'Nikita Smith waffle iron 80 1',
'Nikita Smith knife 10 2',
'Nikita Smith pot 20 3' ]
在.map(line => line.split(" "))
之后
[ [ 'mark johannson', 'waffle iron', '80', '2' ],
[ 'mark johannson', 'blender', '200', '1' ],
[ 'mark johannson', 'knife', '10', '4' ],
[ 'Nikita Smith', 'waffle iron', '80', '1' ],
[ 'Nikita Smith', 'knife', '10', '2' ],
[ 'Nikita Smith', 'pot', '20', '3' ] ]
重要的是要指出阵列的每一行中恰好有四个元素。这些对应于customer name
[index 0],item name
[index 1],price
[index 2]和quantity
[index 3]。
.reduce...
函数将数组转换为JavaScript对象。.reduce((customers, line) => { customers[line[0]] = customers[line[0]] || []; customers[line[0]].push({ name: line[1], price: line[2], quantity: line[3] }); return customers; }, {});
Reduce在这里接受三个参数(虽然我们没有提供另外两个可选参数。)提供的参数是:1)reduce的累加器的当前值由变量customers
表示,数组中的当前行由变量line
表示,以及reduce将构建的起始值 - 由空对象文字{}
提供。
我们的行变量的值是
line[0]
=客户名称line[1]
=产品名称line[2]
=价格line[3]
=数量
在reduce函数中,发生了三件事。
- 从,
customers[line[0]] = customers[line[0]] || [];
,我们(不知何故神奇地)提取每个客户。这样可以保留当前客户(如果存在),或者如果没有客户则将客户设置为空数组。 问题:即使我们将线设置为customers[line[0]] = []
,那么仍然会返回customer name
。这有可能在世界上如何?如果我们将customer
设置为空数组,reduce
如何返回customer
的值?在customers[line[0]] = []
,我们没有把任何东西推到阵列上。 如果我们将客户[line [0]]设置为空数组并且永远不会将line [0]的值推送到客户身上,我绝对会对客户如何在此设置并返回。 - 项目的
name
,price
和quantity
的数据被推送到附加到客户的阵列中。customers[line[0]].push({ name: line[1], price: line[2], quantity: line[3]
- 返回
customer
对象并提供下一次reduce
迭代。当阵列中没有更多行可用于处理时,将返回customer
数组作为最终结果。
line [0]是客户的名字。这意味着:
customers[line[0]] = customers[line[0]] || []
等于这个:
const customerName = line[0];
customers[customerName] = customers[customerName] || [];
它的作用是确保在尝试将对象推送到客户列表之前,实际存在列表。让我们分配并看看会发生什么:
customers['mark johnson'] = customers['mark johnson'] || [];
因此,当没有任何东西时,客户对象被分配给属性'mark johnson'的空列表,或者当前存在的列表。
所以它等同于:
const customerName = line[0];
if (!customers[customerName]) {
customers[customerName] = [];
}
之后的代码基本上是破坏'line'列表,并将其映射到对象的属性,然后推送到上面的列表。所以它等同于:
.reduce((customers, line) => {
const customerName = line[0];
if (!customers[customerName]) {
customers[customerName] = [];
}
const price = line[2];
const quantity = line[3];
const currentLine = {
name: customerName,
price: price,
quantity: quantity
};
customers[customerName].push(currentLine);
return customers;
}, {});
但显然前面的代码更好:)如果使用Destructuring,可能会更清楚一些:
.reduce((customers, [name, price, quantity]) => {
customers[name] = customers[name] || [];
customers[name].push({name, price, quantity});
return customers;
}, {});
希望有所帮助。
以上是关于JavaScript的Reduce如何分配其价值?的主要内容,如果未能解决你的问题,请参考以下文章
javascript JS:如何使用reduce()function.js #javascript #js #reduce查找数字数组的总和
如何在 javascript 中递归使用 reduce() 方法? [复制]