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

IT技术 javascript arrays object
2021-01-25 04:37:23

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

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

6个回答

如果您想将对象映射到某物(在本例中是一个属性)。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(",")
只是一个更新 - 数组推导式已从 ES6 中删除,也许我们会在 ES7 中得到它们。
2021-03-17 04:37:23
这个。但是,如果您需要支持此复古浏览器,则需要为 IE < 9 填充 .map 原型成员。
2021-04-01 04:37:23
@jackweirdy 我很高兴我能提供帮助 :) 对于它的value,就像 map/reduce/filter 不是“pythonic”一样,理解是另一种方式。在 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 很酷
2021-04-02 04:37:23
@Tommi 好评论。我添加了关于 polyfill 的解释以及如果使用下划线时使用 pluck 的建议。
2021-04-06 04:37:23
在咖啡脚本中: users.map((obj) -> obj.name).join(', ')
2021-04-09 04:37:23

那么你总是可以覆盖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);

真正有趣的方法!这种方法对大型阵列的性能有任何影响吗?
2021-03-15 04:37:23
@BadHorsie 不,它不是干的。但是当然您可以在数组之外定义一个函数,然后toString使用 for 循环将该函数分配给所有项方法。或者您可以在处理构造函数时使用这种方法,通过向构造函数toStringprototype属性添加一个方法然而,这个例子只是为了展示基本概念。
2021-03-17 04:37:23
看起来不是很干
2021-04-02 04:37:23
这是一个非常有趣的方法,我没有意识到你可以在 JS 中做到这一点。虽然数据来自 API,所以它可能不适合我的用例,但它绝对值得深思。
2021-04-12 04:37:23

我也遇到过使用该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}
    )
)

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

编辑:我现在已经将它进一步重构为:

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

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

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

对阅读本文的学生的小挑剔。大 O 下降常数。O(2n) 实际上是 O(n),这使得在 Big O 方面两者“相等”。可读性(几乎)总是比性能更重要,特别是如果它只是一个常数因子差异。
2021-03-16 04:37:23
谢谢 :Dreduce没有得到广泛支持map(这很奇怪,因为他们是姐妹)所以我仍在使用你的答案:)
2021-03-16 04:37:23
看看我 6 个月后的编辑,我现在决定我不会雇佣自己......这很狡猾,但并不干净。
2021-04-02 04:37:23
我相信这是最好的答案,因为reduce 方法只迭代一次O(n),而map+join 迭代两次O(2n)。
2021-04-09 04:37:23

在节点或 ES6+ 上:

users.map(u => u.name).join(', ')

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

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

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

arr你的数组在哪里,自然)
2021-03-28 04:37:23
我以前涉足过下划线,但我希望有一种方法可以在本机 JS 中做到这一点 - 将整个库拉入一次使用一种方法有点愚蠢:)
2021-04-03 04:37:23
很公平!我发现自己现在到处都在使用下划线,所以这不是问题。
2021-04-06 04:37:23