web-dev-qa-db-ja.com

オブジェクトの配列の値に対して.joinを実行する

文字列の配列がある場合は、.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(", ");
}

そのコードには何の問題もありません、それは機能しますが、突然、私は単純で簡潔なコード行から非常に命令的な機能に移行しました。これを書くためのもっと簡潔で理想的にもっと機能的な方法はありますか?

221
jackweirdy

オブジェクトを何か(この場合はプロパティ)にマッピングしたい場合。機能的にコーディングしたい場合は、 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があります)。もう1つの方法は、アンダースコアの pluck メソッドを使用することです。

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

オブジェクトの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"
67
basilikum

私は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)は最初の要素が正しく扱われるようになっていますが、残り(aは文字列で、a.nameは未定義)はオブジェクトとして扱われません。

編集:私は今これをさらにリファクタリングしました:

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

aは常に文字列で、bは常にオブジェクトです(reduceオプションのinitialValueパラメータ を使用するため)

6ヵ月後の編集:ああ、私は何を考えていましたか。 "クリーナー"。私はコード神々を怒らせた。

9
jackweirdy

外部ライブラリを使わずにもっと簡単な方法があるかどうかはわかりませんが、私は個人的にはloveunderscore.js これには、配列、コレクションなどを扱うためのたくさんのユーティリティがあります。

下線を使用すると、1行のコードでこれを簡単に実行できます。

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

8
Ed Hinchliffe

ノードまたはES6の場合:

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

2
ariel

オブジェクト配列が変数usersによって参照されているとしましょう。

ES6を使用できる場合、最も簡単な解決策は次のとおりです。

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

そうでなければ、and lodash を使うことができます。

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

オブジェクトと動的キーの場合:"applications\":{\"1\":\"Element1\",\"2\":\"Element2\"}

Object.keys(myObject).map(function (key, index) {
    return myObject[key]
}).join(', ')
1
Davron Achilov

私が知っている古いスレッドですが、これに出会う人にはまだ非常に関連性があります。

ここではArray.mapが提案されていますが、これは私がいつも使っている素晴らしい方法です。 Array.reduceも言及されていた...

このユースケースでは、私は個人的にArray.reduceを使用します。どうして?コードが多少きれいで明確ではないにもかかわらず。 map関数をjoinに渡すよりもはるかに効率的です。

これは、Array.mapが各要素をループ処理して、配列内のすべてのオブジェクトの名前を持つ新しい配列を返す必要があるためです。次にArray.joinは、結合を実行するためにarrayの内容をループします。

あなたはjackweirdysの読みやすさを向上させることができますコードを1行にするためにテンプレートリテラルを使用することによって答えを減らします。 「最近のすべてのブラウザでもサポートされています」

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

確かではありませんが、これらはすべて動作しますが、2つのスキャンを実行しているため最適ではありません。1回のスキャンでこれを実行できます。 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');
0
Jorge Aguilar