366

如果我有一个字符串数组,我可以使用该.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(", ");
}

这段代码没有任何问题,它可以工作,但突然之间,我已经从一个简单、简洁的代码行变成了一个非常命令式的函数。有没有更简洁、更实用的写法?

4

12 回答 12

656

如果您想将对象映射到某物(在本例中为属性)。如果您想进行功能性编码,我认为Array.prototype.map这就是您正在寻找的东西。

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

在现代 JavaScript 中:

console.log([
      {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(",")
于 2013-05-17T11:13:28.897 回答
81

那么你总是可以覆盖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(", ");
    console.log(result);

于 2013-05-17T11:17:03.470 回答
16

我也遇到过使用该reduce方法,这就是它的样子:

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

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

编辑:我现在已经对其进行了进一步的重构:

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

我认为它更干净,因为a它始终是一个字符串,b始终是一个对象(由于使用了可选的initialValue 参数reduce

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

于 2013-06-10T13:38:44.883 回答
10

在节点或 ES6+ 上:

users.map(u => u.name).join(', ')
于 2017-11-14T04:01:11.397 回答
9

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

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

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

于 2013-05-17T11:19:23.200 回答
4

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

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

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

如果没有,那么可以使用lodash :

 _.map(users, function(user) {
     return user.name;
 }).join(', ');
于 2017-11-14T08:34:01.833 回答
2

如果对象和动态键:"applications\":{\"1\":\"Element1\",\"2\":\"Element2\"}

Object.keys(myObject).map(function (key, index) {
    return myObject[key]
}).join(', ')
于 2019-03-11T13:16:02.267 回答
1

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

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

对于这个用例,我个人会使用 Array.reduce。为什么?尽管代码不太干净/清晰。它比通过管道将 map 函数传递给连接更有效。

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

您可以通过使用模板文字将代码放在一行中来提高jackweirdys reduce answer的可读性。“也支持所有现代浏览器”

// a one line answer to this question using modern JavaScript
x.reduce((a, b) => `${a.name || a}, ${b.name}`);
于 2018-08-09T14:30:26.967 回答
0

您可以转换为数组,以便获取对象名称

var objs = [
      {name: "Joe", age: 22},
      {name: "Kevin", age: 24},
      {name: "Peter", age: 21}
    ];
document.body.innerHTML = Object.values(objs).map(function(obj){
   return obj.name;
});

于 2021-02-04T01:55:08.693 回答
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');
于 2019-06-28T20:11:34.407 回答
0

最简单的方法:

const oldArrayOfObjects = [
{name: "Bob", age:40}, 
{name: "Andrew", age:25}, 
{name: "Peter", age:30}];
const newArrayOfStringNames = oldArrayOfObjects.map((OA) => OA.name);
const newArrayOfAges = oldArrayOfObjects.map((OA) => OA.age);
console.log({newArrayOfStringNames, newArrayOfAges})

于 2021-05-21T18:58:26.627 回答
-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"
于 2013-05-17T11:25:03.503 回答