我有一个对象数组,我希望从中获取名称。我试图使用reduce,但问题是reduce返回第一个值为undefined,只返回数组中的最后一个值。我不知道这是为什么? reduce如何处理对象内的字符串?
我的代码:
var data = [ {name: 'Bart'}, {name: 'Lisa'}, {name: 'Maggie'} ]
var result = function(){
var names = data.reduce(function(a, b){
return a.name + ',' + b.name
})
return names
};
var res = result();
console.log(res)
**`output // undefined,Maggie`**
答案 0 :(得分:1)
var names = data.reduce(function (names, item) {
return names + ' ' + item.name;
}, "");
或:
var names = data.map(function (item) { return item.name }).join(" ");
答案 1 :(得分:1)
Reduce为每个元素执行一次回调函数 数组,不包括数组中的孔。
前两个参数是:
累加器(在你的情况下a
)
currentValue(在您的情况下为b
)
InitialValue因此reduce将从索引1开始执行回调函数,跳过第一个索引。第一次累加器是对象{name: 'Bart'}
,第二次是字符串"Bart,Lisa"
var data = [ {name: 'Bart'}, {name: 'Lisa'}, {name: 'Maggie'} ]
var result = function(){
var names = data.reduce(function(a, b){
return (a.name || a) + ',' + b.name
})
return names
};
var res = result();
console.log(res)
对于更干净的解决方案,您可以使用map而不是减少。(更具可读性)
var data = [ {name: 'Bart'}, {name: 'Lisa'}, {name: 'Maggie'} ]
var result = data.map(x =>x.name).join(",");
console.log(result);
答案 2 :(得分:1)
reduce
有两个参数。第一个是累计值,第二个是数组中的元素之一。在开始时,使用提供的累加器,在我的例子中是空字符串。我提供它将是空值undefined
。
arrData.reduce(function (strAccumulator, objElement) {
return (strAccumulator ? strAccumulator + ', ' : '' ) + objElement.name;
}, "");
// ==> "Bart, Lisa, Maggie"
如果您使用下划线,则可以使用pluck
和join执行此更清洁:
_.pluck(arrData, 'name').join(', ');
// ==> "Bart, Lisa, Maggie"
请注意,如果您的对象具有toString
函数,该函数返回您想要的字符串表示形式,则可以省略采摘:
function Simpson(strName) {
this.name = strName;
}
Simpson.prototype.toString = function(){
return this.name;
};
var arrData = [new Simpson('Bart'), new Simpson('Lisa'), new Simpson('Maggie')];
arrData.join(', ');
// ==> "Bart, Lisa, Maggie"
答案 3 :(得分:1)
为什么以及如何
这里有几个答案急于得到正确的答案,但未能建立一个强大,完整的功能。这个答案意味着详尽无遗,让您深入了解为什么我们会选择某些实施而不是其他
<强>合同强>
要使您的函数能够处理所有[{name: String}]
输入( ),您必须处理3个案例
listofNames([]) // ''
listofNames([{name: 'Bart'}]) // 'Bart'
listofNames([{name: 'Bart'},{name: 'Lisa'}, ...]) // 'Bart, Lisa, ...'
[]
)返回空字符串', '
分隔符不存在满足您的要求
您曾要求Array.prototype.reduce
执行此操作,因此我们将从那里开始。你会注意到这个答案是
listOfNames
成为总功能 - 其他几个答案无法容纳( 1 )和( 2 )上面。if
,因为这只需要 - 在reducer中使用if
是浪费
*
const listOfNames = ([x,...xs]) => {
if (x === undefined)
return ''
else
return xs.reduce((acc, {name}) => acc + ', ' + name, x.name)
}
console.log(listOfNames([])) // ''
console.log(listOfNames([{name: 'Bart'}])) // 'Bart'
console.log(listOfNames([{name: 'Bart'}, {name: 'Lisa'}])) // 'Bart, Lisa'
&#13;
推荐
您使用 functional-programming 标记了这个问题,因此我们将从另一个角度来看待这个问题。我们上面做的是重新发明 Array.prototype.join
函数 - 只有我们实际上有点更糟。
console.log([].join(', ')) // ''
console.log(['Bart'].join(', ')) // 'Bart'
console.log(['Bart','Lisa'].join(', ')) // 'Bart, Lisa'
&#13;
我们的函数更具体,不允许我们更改使用的分隔符(始终使用', '
),并假设数组中的每个元素都具有name
属性。
在函数式编程天堂王国中,我们应该尽可能地使我们的函数成为泛型 - 这允许最多的代码回收。
好的,所以我们只需要将对象的数组转换为 names 的数组,而不是重新创建一个非常好的函数,然后使用完美的{{em> 1}}功能
join
&#13;
&#34;但这与其他人说的基本相同&#34;
是的,但显然他们没有意识到为什么它更好。他们认为,因为生成的代码更短,但它更好 - 否则,他们也不会给出const prop = x => y => y[x]
const listOfNames = xs =>
xs.map(prop('name')).join(', ')
console.log(listOfNames([])) // ''
console.log(listOfNames([{name: 'Bart'}])) // 'Bart'
console.log(listOfNames([{name: 'Bart'}, {name: 'Lisa'}])) // 'Bart, Lisa'
解决方案,这些解决方案非常复杂/不完整。
现在你知道为什么某些解决方案比其他解决方案更好,你可以评估哪一个最适合你
测验:您能说出reduce
+ map
解决方案可能比我们的自定义join
解决方案更糟糕的一个原因?
答案 4 :(得分:0)
您需要检查是否设置了上一个值(a)。如果不返回当前值(b)。还传入一个空字符串作为reduce函数的初始值。
var data = [ {name: 'Bart'}, {name: 'Lisa'}, {name: 'Maggie'} ]
var result = function(){
var names = data.reduce(function(a, b){
return a ? a + ',' + b.name : b.name;
},"");
return names;
};
var res = result();
console.log(res);