对对象数组中的值执行.join

jac*_*rdy 239 javascript arrays object

如果我有一个字符串数组,我可以使用该.join()方法获取单个字符串,每个元素用逗号分隔,如下所示:

["Joe", "Kevin", "Peter"].join(", ") // => "Joe, Kevin, Peter"
Run Code Online (Sandbox Code Playgroud)

我有一个对象数组,我想对其中的值执行类似的操作; 所以

[
  {name: "Joe", age: 22},
  {name: "Kevin", age: 24},
  {name: "Peter", age: 21}
]
Run Code Online (Sandbox Code Playgroud)

join仅对name属性执行方法,以实现与以前相同的输出.

目前我有以下功能:

function joinObj(a, attr){
  var out = [];

  for (var i = 0; i < a.length; i++){
    out.push(a[i][attr]);
  }

  return out.join(", ");
}
Run Code Online (Sandbox Code Playgroud)

这段代码没有任何问题,它可以工作,但突然之间,我已经从一个简单,简洁的代码行转变为一个非常重要的代码.是否有更简洁,更理想的写作方式?

Ben*_*aum 441

如果要将对象映射到某个东西(在本例中为属性).Array.prototype.map如果你想在功能上进行编码,我想你正在寻找什么.

[
  {name: "Joe", age: 22},
  {name: "Kevin", age: 24},
  {name: "Peter", age: 21}
].map(function(elem){
    return elem.name;
}).join(",");
Run Code Online (Sandbox Code Playgroud)

在现代JavaScript中:

[
  {name: "Joe", age: 22},
  {name: "Kevin", age: 24},
  {name: "Peter", age: 21}
].map(e => e.name).join(",");
Run Code Online (Sandbox Code Playgroud)

(小提琴)

如果您想支持不是ES5投诉的旧版浏览器,您可以对其进行填充(上面的MDN页面上有一个polyfill).另一种选择是使用underscorejs的pluck方法:

var users = [
      {name: "Joe", age: 22},
      {name: "Kevin", age: 24},
      {name: "Peter", age: 21}
    ];
var result = _.pluck(users,'name').join(",")
Run Code Online (Sandbox Code Playgroud)


bas*_*kum 70

那么你总是可以覆盖toString你的对象的方法:

var arr = [
    {name: "Joe", age: 22, toString: function(){return this.name;}},
    {name: "Kevin", age: 24, toString: function(){return this.name;}},
    {name: "Peter", age: 21, toString: function(){return this.name;}}
];

var result = arr.join(", ");
//result = "Joe, Kevin, Peter"
Run Code Online (Sandbox Code Playgroud)

  • 这是一个非常有趣的方法,我没有意识到你可以在 JS 中做到这一点。虽然数据来自 API,所以它可能不适合我的用例,但它绝对值得深思。 (2认同)
  • 看起来不是很干 (2认同)
  • @BadHorsie不,这不是DRY.但是当然你可以在数组之外定义一个函数,然后使用for循环将此函数分配给所有项的`toString`方法.或者,您可以在处理构造函数时使用此方法,方法是将一个`toString`方法添加到构造函数的`prototype`属性中.然而,这个例子应该只显示基本概念. (2认同)

小智 12

const lists  = [
  {name: "Joe", age: 22},
  {name: "Kevin", age: 24},
  {name: "Peter", age: 21}
]

const joinedStr = lists.map((list) => list.name).join(" ")

console.log('joined',joinedStr)
Run Code Online (Sandbox Code Playgroud)

这应该可以做到,因为映射将返回一个字符串数组,然后您可以加入它


jac*_*rdy 11

我也遇到过使用这种reduce方法,它看起来像是这样的:

[
  {name: "Joe", age: 22},
  {name: "Kevin", age: 24},
  {name: "Peter", age: 21}
].reduce(function (a, b) {return (a.name || a) + ", " + b.name})
Run Code Online (Sandbox Code Playgroud)

(a.name || a)是第一个元素被正确处理,但其余的(其中a是一个字符串,因此a.name是未定义的)不被视为对象.

编辑:我现在已经进一步重构了这个:

x.reduce(function(a, b) {return a + ["", ", "][+!!a.length] + b.name;}, "");
Run Code Online (Sandbox Code Playgroud)

我相信这是吸尘器,a始终是一个字符串,b始终是一个对象(由于使用的可选参数初值reduce)

编辑6个月后:哦,我在想什么."清洁器".我激怒了代码众神.

  • 看看我 6 个月后的编辑,我现在决定我不会雇佣自己......这很狡猾,但并不干净。 (2认同)

ari*_*iel 10

在节点或 ES6+ 上:

users.map(u => u.name).join(', ')
Run Code Online (Sandbox Code Playgroud)


Ed *_*ffe 9

我不知道是否有一种更简单的方法可以在不使用外部库的情况下完成它,但我个人喜欢使用 大量实用程序来处理数组,集合等的underscore.js.

使用下划线,您可以使用一行代码轻松完成此操作:

_.pluck(arr, 'name').join(', ')


C'e*_*Vie 7

假设对象数组由变量引用users

如果可以使用 ES6 那么最简单的解决方案将是:

users.map(user => user.name).join(', ');
Run Code Online (Sandbox Code Playgroud)

如果没有,可以使用lodash :

 _.map(users, function(user) {
     return user.name;
 }).join(', ');
Run Code Online (Sandbox Code Playgroud)