如何使用javascript减少数组中对象的函数来获取字符串值

时间:2017-02-14 09:06:29

标签: javascript arrays functional-programming

我有一个对象数组,我希望从中获取名称。我试图使用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`**

fiddle

5 个答案:

答案 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"

如果您使用下划线,则可以使用pluckjoin执行此更清洁:

_.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, ...'
  1. 空数组([])返回空字符串
  2. 单个名称将只返回该名称 - ', '分隔符不存在
  3. 2个或更多名称的数组将返回
  4. 之间带分隔符的名称

    满足您的要求

    您曾要求Array.prototype.reduce执行此操作,因此我们将从那里开始。你会注意到这个答案是

    • 适用于上述所有输入方案,使listOfNames成为总功能 - 其他几个答案无法容纳( 1 )和( 2 )上面。
    • 它只使用 if,因为这只需要 - 在reducer中使用if是浪费 *

    &#13;
    &#13;
    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;
    &#13;
    &#13;

    推荐

    您使用 functional-programming 标记了这个问题,因此我们将从另一个角度来看待这个问题。我们上面做的是重新发明 Array.prototype.join函数 - 只有我们实际上有点更糟

    &#13;
    &#13;
    console.log([].join(', '))               // ''
    console.log(['Bart'].join(', '))         // 'Bart'
    console.log(['Bart','Lisa'].join(', '))  // 'Bart, Lisa'
    &#13;
    &#13;
    &#13;

    我们的函数更具体,不允许我们更改使用的分隔符(始终使用', '),并假设数组中的每个元素都具有name属性。

    在函数式编程天堂王国中,我们应该尽可能地使我们的函数成为泛型 - 这允许最多的代码回收。

    好的,所以我们只需要将对象的数组转换为 names 的数组,而不是重新创建一个非常好的函数,然后使用完美的{{em> 1}}功能

    &#13;
    &#13;
    join
    &#13;
    &#13;
    &#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);