[英]Converting Array to Object using Reduce
Can someone explain how this is working. 有人可以解释这是如何工作的。
Learning to use Array.reduce() 学习使用Array.reduce()
var votes = ['tacos','pizza','pizza','tacos','fries','ice cream','ice cream','pizza'];
var initialValue = {}
var reducer = function(tally, vote) {
if (!tally[vote]) {
tally[vote] = 1;
} else {
tally[vote] = tally[vote] + 1;
}
return tally;
}
var result = votes.reduce(reducer, initialValue)
The way how reduce works is pretty similar to map
or filter
. reduce的工作方式与
map
或filter
非常相似。 In this case, the reducer is responsible for reducing the array of objects into one object. 在这种情况下,reducer负责将对象数组简化为一个对象。
The reducer function iterates through all elements of your array. reducer函数遍历数组的所有元素。 The function is called with two arguments,
tally
- result of reducing so far and vote
- array element that is currently being processed . 该函数使用两个参数调用,
tally
到目前为止减少的结果和当前正在处理的 vote
数组元素 。
If tally
does not have a property named just like the element that is currently being processed/reduced, it adds such a key to the object and sets its value to one. 如果
tally
没有像当前正在处理/缩减的元素那样命名的属性,则它将这样的键添加到对象并将其值设置为1。 Otherwise (key is present), it's incremented by one. 否则(存在密钥),它将增加一。
Basically Array.prototype.reduce()
method applies a function against an accumulator and each value of the array to reduce it to a single value. 基本上,
Array.prototype.reduce()
方法对一个累加器和数组的每个值应用一个函数,以将其减少为单个值。
In your example the reduced value (the result of a count operation) is assigned as a property of an object called tally
which is returned by .reduce()
; 在您的示例中,将减小的值(计数操作的结果)分配为称为
tally
的对象的属性,该对象由.reduce()
返回;
I comment your with a brief explanation: 我用简短的解释评论您:
// your data in an array var votes = ['tacos','pizza','pizza','tacos','fries','ice cream','ice cream','pizza']; // optional value to use as the first argument to the first call of the callback when using Array.prototype.reduce(). var initialValue = {} // tally = previousValue and vote = currentValue var reducer = function(tally, vote) { // if tally is not assign as a key in tally object, add key and add value of one, (basically count 1 for one element in your votes array) if (!tally[vote]) { tally[vote] = 1; } else { // otherwise if tally object has already this key, increment its value by one, (basically it counts how many times each item in votes array is present in the array) tally[vote] = tally[vote] + 1; } return tally; } var result = votes.reduce(reducer, initialValue); console.log(result);
Notes: you can actually avoid using of declaring a variable for initialValue
and instead using only var result = votes.reduce(reducer, {});
注意:实际上,您可以避免使用为
initialValue
声明变量,而只使用var result = votes.reduce(reducer, {});
API documentation: API文档:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
Some more examples and brief explanation: 更多示例和简要说明:
https://www.airpair.com/javascript/javascript-array-reduce https://www.airpair.com/javascript/javascript-array-reduce
I inserted some console.log messages in your code and this helped me understand what was going on. 我在您的代码中插入了一些console.log消息,这有助于我了解发生了什么。
var votes = ['tacos', 'pizza', 'pizza', 'tacos', 'fries', 'ice cream', 'ice cream', 'pizza']; var initialValue = {} var reducer = function(tally, vote) { console.log("tally: ", tally); console.log("vote: ", vote); console.log("tally[vote]: ", tally[vote]); if (!tally[vote]) { tally[vote] = 1; } else { tally[vote] = tally[vote] + 1; } return tally; } var result = votes.reduce(reducer, initialValue) console.log("result: " + JSON.stringify(result));
There's plenty of verbose explanations of reduce
here and other places, but I think a simple visual demonstration might help 在这里和其他地方有很多关于
reduce
的冗长解释,但我认为简单的视觉演示可能会有所帮助
[1,2,3].reduce(function(a,b) { return a + b }, 0)
// (((0 + 1) + 2) + 3)
// => 6
You can see: 您可以看到:
reduce
reduce
的结果 Now as for your code, we're not building a sum of numbers, we're building up an Object that holds the tally count of each string in an array. 现在,对于您的代码,我们并没有建立数字的总和,而是建立了一个Object ,它保存数组中每个字符串的计数计数。
There's no point in me explaining what everyone else did, but it's not surprising this might've been confusing for you because no one explained that this is abuse of an Object. 我没有必要解释其他所有人的所作所为,但这不足为奇,这并不奇怪,因为没有人解释这是对Object的滥用。
In truth, an Object is actually not the best data structure choice for this reduction. 实际上,对于这种简化,对象实际上不是最佳的数据结构选择。 Here, an Object is used to emulate the behaviour of a Map .
在这里,对象用于模拟Map的行为。
We'll set initialValue
to a new Map()
and you'll see how the reducer
uses more descriptive syntax within. 我们将
initialValue
设置为new Map()
然后您将了解reducer
如何在其中使用更多描述性语法。 Note comments aren't even necessary because the code says everything it needs to. 注意注释甚至不是必需的,因为代码说明了它所需要的一切。
var votes = ['tacos','pizza','pizza','tacos','fries','ice cream','ice cream','pizza'] var initialValue = new Map() var reducer = function (tally, vote) { if (tally.has(vote)) return tally.set(vote, tally.get(vote) + 1) else return tally.set(vote, 1) } var result = votes.reduce(reducer, initialValue) console.log(Array.from(result.entries()))
Output 输出量
[
[ "tacos", 2 ],
[ "pizza", 3 ],
[ "fries", 1 ],
[ "ice cream", 2 ]
]
I can show you that the visual representation of the sum via reduce is correct/accurate by writing a reducer that builds a string instead of actually adding the numbers 我可以通过编写一个构造字符串而不是实际将数字相加的reduce来向您展示通过reduce进行的总和的视觉表示是正确/准确的
var initialValue = 0 var reducer = function(a,b) { return '(' + a + ' + ' + b + ')' } var result = [1,2,3].reduce(reducer, initialValue) console.log(result) // (((0 + 1) + 2) + 3)
This technique might be useful for you when trying to understand/debug your own reducers 尝试了解/调试自己的Reducer时,此技术可能对您有用
The reduce() method reduces the array to a single value . reduce()方法将数组缩小为单个值 。
The reduce() method executes a provided function for each value of the array (from left-to-right ). reduce()方法为数组的每个值 ( 从左到右 ) 执行 提供的函数 。
The return value of the function is stored in an accumulator (result/total). 函数的返回值 存储在累加器中(结果/总计)。
You have this given list : 您有此给定列表 :
var votes = ['tacos','pizza','pizza','tacos','fries','ice cream','ice cream','pizza'];
Then you make an Initial List . 然后创建一个初始列表 。 You can modify this and the function will be applied for both lists.
您可以对此进行修改,并且该功能将同时应用于两个列表。
var initialValue = {}
"reducer" is initialized as a function . “ reducer”被初始化为一个函数 。 The reason that we place the function in "reducer" is so we can call it more easily further on.
之所以将函数放置在“ reducer”中,是因为我们可以更轻松地对其进行调用。 You can do whatever you want in this function and it will be executed on the list in the upcoming steps
您可以在此函数中做任何您想做的事,它将在接下来的步骤中在列表中执行
var reducer = function(tally, vote) {
if (!tally[vote]) {
tally[vote] = 1;
} else {
tally[vote] = tally[vote] + 1;
}
return tally;
}
Finally, the result of the function is stored into the variable. 最后,函数的结果 存储到变量中。
var result = votes.reduce(reducer, initialValue)
Well, let's try to expand the iteration: 好吧,让我们尝试扩展迭代:
When you execute 执行时
votes.reduce(reducer, initialValue)
It actually does this: 它实际上是这样做的:
reducer(initialValue, votes[0]); // step1, return {'tacos': 1}
reducer(returnedValueOfStep1, votes[1]); // step2, return {'tacos': 1, 'pizza': 1}
reducer(returnedValueOfStep2, votes[2]); // step3, return {'tacos': 1, 'pizza': 2}
reducer(returnedValueOfStep3, votes[3]); // step4 ...
reducer(returnedValueOfStep4, votes[4]); // step5 ...
reducer(returnedValueOfStep5, votes[5]); // step6 ...
reducer(returnedValueOfStep6, votes[6]); // step7 ...
reducer(returnedValueOfStep7, votes[7]); // step8 ...
I think it quite clear right now. 我认为现在很清楚。
And usually, if we do not provide initialValue as the second parameter for reduce, it will take the first element of array as the initialValue, and starts iteration from the second one: 通常,如果我们不提供initialValue作为reduce的第二个参数,它将数组的第一个元素作为initialValue,并从第二个元素开始迭代:
reducer(votes[0], votes[1]); // step1 ...
reducer(returnedValueOfStep1, votes[2]); // step2 ...
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.