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


273

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

["Joe", "Kevin", "Peter"].join(", ") // => "Joe, Kevin, Peter"

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

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

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

目前,我具有以下功能:

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

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

  return out.join(", ");
}

该代码没有任何问题,它可以正常工作,但是突然之间,我已经从简单,简洁的代码行变成了非常必要的功能。是否有更简洁,更理想的功能编写方式?


1
以一种语言为例,Pythonic的实现方法是" ,".join([i.name for i in a])
jackweirdy 2013年

6
在ES6中,您可以这样做:users.map(x => x.name).join(', ');
totymedli

Answers:


496

如果要将对象映射到某物(在这种情况下为属性)。Array.prototype.map如果您想进行功能编码,我认为您正在寻找的是。

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

在现代JavaScript中:

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

(小提琴)

如果要支持不兼容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(",")

1
这个。但是,如果需要支持此复古浏览器,则需要对IE <9的.map原型成员进行填充。
汤米

@Tommi很好的评论。我添加了有关polyfill的说明,并建议在使用下划线时使用pluck。
本杰明·格林鲍姆

@jackweirdy我很高兴可以为您提供帮助:),因为它的价值,就像map / reduce / filter不是'pythonic'一样,而comprehensions是另一种方式。在JavaScript的新规范(Harmony)和某些浏览器(firefox)中,您具有pythonic理解。您可以执行[x.name for x of users](spec wiki.ecmascript.org/doku.php?id=harmony:array_comprehensions)。值得一提的是,就像使用map / reduce / filter一样,它并不是非常“ pythonic”,JavaScript中可能还有另一种方式。通过coffeescript.org, CoffeeScript对他们很酷
本杰明·格林鲍姆

只是更新-数组理解已从ES6中删除,也许我们可以在ES7中使用它们。
本杰明·格伦鲍姆

在咖啡脚本中:users.map((obj) -> obj.name).join(', ')
Kesha Antonov

71

好吧,您始终可以覆盖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"

2
这是一个非常有趣的方法,我没有意识到您可以在JS中做到这一点。数据虽然来自API,所以它可能不适合我的用例,但绝对值得深思。
jackweirdy

3
看起来不是很干燥
-BadHorsie

3
@BadHorsie不,它不是干的。但是当然,您可以在数组外部定义一个函数,然后toString使用for循环将此函数分配给所有项目的方法。或者在处理构造函数时,可以通过向构造函数toStringprototype属性添加一个方法来使用这种方法。但是,此示例仅应说明基本概念。
basilikum

13

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

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

使用(a.name || a)is可以正确处理第一个元素,但不会将其余元素(其中a是字符串,因此a.name未定义)视为对象。

编辑:我现在将其进一步重构为:

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

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

六个月后编辑:哦,我在想什么。“清洁器”。我已经激怒了众神密码。


谢谢:D reduce没有得到广泛的支持map(这很奇怪,因为他们是姐妹们),所以我仍在使用您的答案:)
jackweirdy 2013年

在6个月后查看我的编辑内容后,我现在决定不雇用自己了……这很狡猾,但不干净。
jackweirdy 2013年

9

我不知道有没有使用外部库的简便方法,但是我个人喜欢 underscore.js,它具有大量用于处理数组,集合等的实用程序。

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

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


之前我涉猎过下划线,但是我希望能在本机JS中做到这一点
有点笨拙,

arr您的阵列自然在哪里)
Ed Hinchliffe

很公平!我发现自己现在在所有地方都使用下划线,因此这不是问题。
Ed Hinchliffe


3

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

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

users.map(user => user.name).join(', ');

如果没有,可以使用lodash

 _.map(users, function(user) {
     return user.name;
 }).join(', ');


0

我知道一个旧线程,但仍然与遇到此问题的任何人都非常相关。

这里建议使用Array.map,这是我一直使用的很棒的方法。还提到了Array.reduce ...

我将针对此用例亲自使用Array.reduce。为什么?尽管代码不太干净/清晰。它比将map函数传递给联接要有效得多。

这样做的原因是因为Array.map必须遍历每个元素才能返回具有该数组中所有对象名称的新数组。然后Array.join循环遍历array的内容以执行连接。

通过使用模板文字将代码放在一行上,可以提高jackweirdys减少答案的可读性。“所有现代浏览器也都支持”

// a one line answer to this question using modern JavaScript
x.reduce((a, b) => `${a.name || a}, ${b.name}`);

0

不能确定,但​​是所有这些答案都可以正常工作,但不是最佳选择,因为它们正在执行两次扫描,您可以在一次扫描中执行此操作。即使O(2n)被认为是O(n)总是比真正的O(n)好。

const Join = (arr, separator, prop) => {
    let combined = '';
    for (var i = 0; i < arr.length; i++) {
        combined = `${combined}${arr[i][prop]}`;
        if (i + 1 < arr.length)
            combined = `${combined}${separator} `;
    }
    return combined;
}

这看起来像是旧学校,但是允许我做这样的事情:

skuCombined = Join(option.SKUs, ',', 'SkuNum');

-1

试试这个

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

function joinObj(a, attr) {
  var out = []; 
  for (var i=0; i<a.length; i++) {  
    out.push(a[i][attr]); 
  } 
 return out.join(", ");
}

var z = joinObj(x,'name');
z > "Joe, Kevin, Peter"
var y = joinObj(x,'age');
y > "22, 24, 21"

2
该功能与问题中的功能相同,但通用性较差,因为您已对name属性进行了硬编码。(a[i].name没有使用你的函数的name参数,它是相当于a[i]['name']
NNNNNN
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.