オブジェクトの配列から、プロパティの値を配列として抽出します

1193
hyde 2013-10-26 03:13.

次の構造のJavaScriptオブジェクト配列があります。

objArray = [ { foo: 1, bar: 2}, { foo: 3, bar: 4}, { foo: 5, bar: 6} ];

各オブジェクトからフィールドを抽出し、値を含む配列を取得しfooたいと思い[ 1, 3, 5 ]ます。たとえば、fieldはarrayを与えます。

私はこの些細なアプローチでこれを行うことができます:

function getFields(input, field) {
    var output = [];
    for (var i=0; i < input.length ; ++i)
        output.push(input[i][field]);
    return output;
}

var result = getFields(objArray, "foo"); // returns [ 1, 3, 5 ]

カスタムユーティリティ関数が不要になるように、これを行うためのよりエレガントなまたは慣用的な方法はありますか?


jQueryを使用してJSオブジェクトを配列に変換するについての注意、それは単一のオブジェクトを配列に変換する方法をカバーしています

17 answers

1608
Jalasem 2017-10-12 07:33.

これを達成するためのより短い方法は次のとおりです。

let result = objArray.map(a => a.foo);

または

let result = objArray.map(({ foo }) => foo)

確認することもできArray.prototype.map()ます。

640
Niet the Dark Absol 2013-10-26 03:14.

はい。ただし、JavaScriptのES5機能に依存しています。これは、IE8以前では機能しないことを意味します。

var result = objArray.map(function(a) {return a.foo;});

ES6互換のJSインタープリターでは、簡潔にするために矢印関数を使用できます。

var result = objArray.map(a => a.foo);

Array.prototype.mapドキュメント

53
tomb 2015-04-16 17:16.

Lodashの_.pluck()関数またはUnderscoreの_.pluck()関数を確認してください。どちらも、1回の関数呼び出しで必要なことを正確に実行します。

var result = _.pluck(objArray, 'foo');

更新: _.pluck()Lodash v4.0.0から削除され、Nietの回答に_.map()類似したものとの組み合わせが優先されます_.pluck()アンダースコアで引き続き使用できます

更新2: Markオブジェクトの配列から、プロパティの値を配列として抽出しますで指摘しオブジェクトの配列から、プロパティの値を配列として抽出します、Lodash v4と4.3の間のどこかで、この機能を再び提供する新しい関数が追加されました。_.property()オブジェクト内のプロパティの値を取得するための関数を返す省略形の関数です。

さらに、_.map()に渡される2番目のパラメータとして文字列を渡すことができるようになりました_.property()。結果として、次の2行は、Lodash4より前の上記のコードサンプルと同等です。

var result = _.map(objArray, 'foo');
var result = _.map(objArray, _.property('foo'));

_.property()、したがって_.map()、サブプロパティにアクセスするために、ドットで区切られた文字列または配列を指定することもできます。

var objArray = [
    {
        someProperty: { aNumber: 5 }
    },
    {
        someProperty: { aNumber: 2 }
    },
    {
        someProperty: { aNumber: 9 }
    }
];
var result = _.map(objArray, _.property('someProperty.aNumber'));
var result = _.map(objArray, _.property(['someProperty', 'aNumber']));

_.map()上記の例の両方の呼び出しはを返し[5, 2, 9]ます。

関数型プログラミングにもう少し興味がある R.pluck()場合は、Ramdaの関数を見てください。これは次のようになります。

var result = R.pluck('foo')(objArray);  // or just R.pluck('foo', objArray)
47
pscl 2017-02-06 16:13.

JSのみのソリューションについて言えば、エレガントではないかもしれませんが、単純なインデックス付きforループの方が他のループよりもパフォーマンスが高いことがわかりました。

100000要素配列から単一のプロパティを抽出する(jsPerfを介して)

従来のforループ368Ops / sec

var vals=[];
for(var i=0;i<testArray.length;i++){
   vals.push(testArray[i].val);
}

ES6 for..of loop 303 Ops / sec

var vals=[];
for(var item of testArray){
   vals.push(item.val); 
}

Array.prototype.map 19 Ops / sec

var vals = testArray.map(function(a) {return a.val;});

TL; DR-.map()は遅いですが、読みやすさがパフォーマンスよりも価値があると感じた場合は、自由に使用してください。

編集#2:2019年6月-jsPerfリンクが壊れ、削除されました。

20
Tejas Patel 2016-02-09 18:00.

クロスブラウザの保証には、lodashやunderscoreなどのライブラリを使用することをお勧めします。

Lodashでは、次の方法で配列内のプロパティの値を取得できます

_.map(objArray,"foo")

アンダースコアで

_.pluck(objArray,"foo")

両方が戻ります

[1, 2, 3]
15
Alnitak 2013-10-26 03:15.

使用Array.prototype.map

function getFields(input, field) {
    return input.map(function(o) {
        return o[field];
    });
}

ES5より前のブラウザのシムについては、上記のリンクを参照してください。

13
Yuxuan Chen 2018-07-11 07:36.

ES6では、次のことができます。

const objArray = [{foo: 1, bar: 2}, {foo: 3, bar: 4}, {foo: 5, bar: 6}]
objArray.map(({ foo }) => foo)
7
Rogier Spieker 2016-11-20 00:02.

一方でmap、オブジェクトのリストから「列」を選択するための適切な解決策である、それは欠点があります。列が存在するかどうかを明示的にチェックしないと、エラーがスローされ、(せいぜい)が提供されますundefinedreduceプロパティを無視したり、デフォルト値を設定したりできるソリューションを選択します。

function getFields(list, field) {
    //  reduce the provided list to an array only containing the requested field
    return list.reduce(function(carry, item) {
        //  check if the item is actually an object and does contain the field
        if (typeof item === 'object' && field in item) {
            carry.push(item[field]);
        }

        //  return the 'carry' (which is the list of matched field values)
        return carry;
    }, []);
}

jsbinの例

これは、提供されたリストの項目の1つがオブジェクトではないか、フィールドを含まない場合でも機能します。

アイテムがオブジェクトでない場合やフィールドが含まれていない場合は、デフォルト値をネゴシエートすることで、より柔軟にすることもできます。

function getFields(list, field, otherwise) {
    //  reduce the provided list to an array containing either the requested field or the alternative value
    return list.reduce(function(carry, item) {
        //  If item is an object and contains the field, add its value and the value of otherwise if not
        carry.push(typeof item === 'object' && field in item ? item[field] : otherwise);

        //  return the 'carry' (which is the list of matched field values)
        return carry;
    }, []);
}

jsbinの例

返される配列の長さは提供された配列と同じになるため、これはmapと同じになります。(この場合、amapはaよりもわずかに安いですreduce):

function getFields(list, field, otherwise) {
    //  map the provided list to an array containing either the requested field or the alternative value
    return list.map(function(item) {
        //  If item is an object and contains the field, add its value and the value of otherwise if not
        return typeof item === 'object' && field in item ? item[field] : otherwise;
    }, []);
}

jsbinの例

そして、最も柔軟なソリューションがあります。これは、代替値を提供するだけで両方の動作を切り替えることができるソリューションです。

function getFields(list, field, otherwise) {
    //  determine once whether or not to use the 'otherwise'
    var alt = typeof otherwise !== 'undefined';

    //  reduce the provided list to an array only containing the requested field
    return list.reduce(function(carry, item) {
        //  If item is an object and contains the field, add its value and the value of 'otherwise' if it was provided
        if (typeof item === 'object' && field in item) {
            carry.push(item[field]);
        }
        else if (alt) {
            carry.push(otherwise);
        }

        //  return the 'carry' (which is the list of matched field values)
        return carry;
    }, []);
}

jsbinの例

上記の例(うまくいけば)がこれが機能する方法にいくつかの光を当てるように、関数を利用してArray.concat関数を少し短くしましょう。

function getFields(list, field, otherwise) {
    var alt = typeof otherwise !== 'undefined';

    return list.reduce(function(carry, item) {
        return carry.concat(typeof item === 'object' && field in item ? item[field] : (alt ? otherwise : []));
    }, []);
}

jsbinの例

7
Eugen Sunic 2018-07-14 23:27.

一般に、配列内にあるオブジェクト値を推定する場合(質問で説明されているように)、reduce、map、および配列の破棄を使用できます。

ES6

let a = [{ z: 'word', c: 'again', d: 'some' }, { u: '1', r: '2', i: '3' }];
let b = a.reduce((acc, obj) => [...acc, Object.values(obj).map(y => y)], []);

console.log(b)

forinループを使用する同等の方法次のとおりです。

for (let i in a) {
  let temp = [];
  for (let j in a[i]) {
    temp.push(a[i][j]);
  }
  array.push(temp);
}

生成された出力: ["word"、 "again"、 "some"、 "1"、 "2"、 "3"]

5
TechWisdom 2018-04-07 04:16.

配列のようなオブジェクトもサポートする場合は、Array.from(ES2015)を使用します。

Array.from(arrayLike, x => x.foo);

Array.prototype.map()メソッドに対する利点は、入力をSetにすることもできることです。

let arrayLike = new Set([{foo: 1}, {foo: 2}, {foo: 3}]);
5
Chris Magnuson 2019-04-28 04:17.

ES6 +で複数の値が必要な場合は、次のように機能します

objArray = [ { foo: 1, bar: 2, baz: 9}, { foo: 3, bar: 4, baz: 10}, { foo: 5, bar: 6, baz: 20} ];

let result = objArray.map(({ foo, baz }) => ({ foo, baz }))

これ{foo, baz}は、左側がオブジェクトデストラクタリングを使用しているように機能し、矢印の右側はES6の拡張オブジェクトリテラル{foo: foo, baz: baz}によるものと同等です。

5
Qui-Gon Jinn 2020-05-11 14:55.

ネストされた配列がある場合は、次のように機能させることができます。

const objArray = [ 
     { id: 1, items: { foo:4, bar: 2}},
     { id: 2, items: { foo:3, bar: 2}},
     { id: 3, items: { foo:1, bar: 2}} 
    ];

    let result = objArray.map(({id, items: {foo}}) => ({id, foo}))
    
    console.log(result)

4
sitifensys 2013-10-26 03:54.

それはあなたの「より良い」の定義に依存します。

他の回答は、自然で(特に機能的なスタイルに慣れている人にとって)簡潔なマップの使用を指摘しています。私はそれを使用することを強くお勧めします(少数のIE8-IT担当者を気にしない場合)。したがって、「より良い」が「より簡潔」、「維持可能」、「理解可能」を意味する場合、そうです、それははるかに優れています。

一方、この美しさは追加費用なしでは実現できません。私はマイクロベンチの大ファンではありませんが、ここで小さなテストを行いました。結果は予測可能であり、古い醜い方法はマップ関数よりも速いようです。したがって、「より良い」が「より速い」を意味する場合は、いいえ、古い学校のファッションにとどまります。

繰り返しますが、これは単なるマイクロベンチであり、の使用に反対することを主張するものではありませんmap。それは私の2セントです:)。

4
jafarmlp 2020-09-29 11:48.

オブジェクト配列からさまざまなフィールドを収集する例

let inputArray = [
  { id: 1, name: "name1", value: "value1" },
  { id: 2, name: "name2", value: "value2" },
];

let ids = inputArray.map( (item) => item.id);
let names = inputArray.map((item) => item.name);
let values = inputArray.map((item) => item.value);

console.log(ids);
console.log(names);
console.log(values);

結果:

[ 1, 2 ]
[ 'name1', 'name2' ]
[ 'value1', 'value2' ]
1
Niko Gamulin 2015-11-28 22:32.

関数マップは、オブジェクト配列を扱う場合に適しています。すでに多くの良い回答が投稿されていますが、フィルターと組み合わせてマップを使用する例が役立つ場合があります。

値が未定義のプロパティを除外する場合、または特定のプロパティのみを除外する場合は、次のようにします。

    var obj = {value1: "val1", value2: "val2", Ndb_No: "testing", myVal: undefined};
    var keysFiltered = Object.keys(obj).filter(function(item){return !(item == "Ndb_No" || obj[item] == undefined)});
    var valuesFiltered = keysFiltered.map(function(item) {return obj[item]});

https://jsfiddle.net/ohea7mgk/

1
Akash Jain 2019-02-06 20:34.

上記の回答は、単一のプロパティを抽出するのに適しています。オブジェクトの配列から複数のプロパティを抽出する場合はどうでしょうか。 これが解決策です!! その場合は、単に_.pick(object、[paths])を使用できます。

_.pick(object, [paths])

objArrayに以下のような3つのプロパティを持つオブジェクトがあると仮定しましょう

objArray = [ { foo: 1, bar: 2, car:10}, { foo: 3, bar: 4, car:10}, { foo: 5, bar: 6, car:10} ];

次に、すべてのオブジェクトからfooプロパティとbarプロパティを抽出し、それらを個別の配列に格納します。まず、mapを使用して配列要素を反復処理し、次にLodash Library Standard _.pick()メソッドを適用します。

これで、「foo」および「bar」プロパティを抽出できるようになりました。

var newArray = objArray.map((element)=>{ return _.pick(element, ['foo','bar'])}) console.log(newArray);

結果は[{foo:1、bar:2}、{foo:3、bar:4}、{foo:5、bar:6}]になります。

楽しい!!!

1
GavinBelson 2020-08-14 08:26.

オブジェクトの配列から複数のプロパティを簡単に抽出します。

let arrayOfObjects = [
  {id:1, name:'one', desc:'something'},
  {id:2, name:'two', desc:'something else'}
];

//below will extract just the id and name
let result = arrayOfObjects.map(({id, name}) => ({id, name}));

result になります [{id:1, name:'one'},{id:2, name:'two'}]

マップ機能で必要に応じてプロパティを追加または削除します

Related questions

MORE COOL STUFF

「水曜日」シーズン1の中心には大きなミステリーがあります

「水曜日」シーズン1の中心には大きなミステリーがあります

Netflixの「水曜日」は、典型的な10代のドラマ以上のものであり、実際、シーズン1にはその中心に大きなミステリーがあります.

一部のファンがハリー・スタイルズとオリビア・ワイルドの「非常に友好的な」休憩が永続的であることを望んでいる理由

一部のファンがハリー・スタイルズとオリビア・ワイルドの「非常に友好的な」休憩が永続的であることを望んでいる理由

一部のファンが、オリビア・ワイルドが彼女とハリー・スタイルズとの間の「難しい」が「非常に友好的」な分割を恒久的にすることを望んでいる理由を見つけてください.

エリザベス女王の死後、ケイト・ミドルトンはまだ「非常に困難な時期」を過ごしている、と王室の専門家が明らかにする 

エリザベス女王の死後、ケイト・ミドルトンはまだ「非常に困難な時期」を過ごしている、と王室の専門家が明らかにする&nbsp;

エリザベス女王の死後、ケイト・ミドルトンが舞台裏で「非常に困難な時期」を過ごしていたと伝えられている理由を調べてください.

ウィリアム王子は「非常に現代的なお父さん」だと王室の専門家は言う

ウィリアム王子は「非常に現代的なお父さん」だと王室の専門家は言う

ある王室の専門家が、特に彼の家族の他の王室の両親と比較して、ウィリアム王子が「非常に現代的な父親」であると考える理由を学びましょう.

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セント ヘレナ島のジェイコブズ ラダーは 699 段の真っ直ぐ上る階段で、頂上に到達すると証明書が発行されるほどの難易度です。

The Secrets of Airline Travel Quiz

The Secrets of Airline Travel Quiz

Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

バイオニック読書はあなたをより速く読むことができますか?

バイオニック読書はあなたをより速く読むことができますか?

BionicReadingアプリの人気が爆発的に高まっています。しかし、それは本当にあなたを速読術にすることができますか?

メイミー・ジョンソン、ニグロリーグでピッチングした女性、82歳で死去

メイミー・ジョンソン、ニグロリーグでピッチングした女性、82歳で死去

写真提供者:Khue Bui / AP Mamie Johnsonは、ニグロリーグでプレーする3人の女性の1人で、82歳で亡くなりました。ジョンソンは子供の頃から野球を始め、最初に全米女子プロ野球に挑戦しました。 17歳のリーグだが、黒人だったのでフィールドへの出場は許されなかった。

グローアップゴール:カルメンデラヴァラードは時代を超えた魅力の縮図です

グローアップゴール:カルメンデラヴァラードは時代を超えた魅力の縮図です

ジャックミッチェル/ゲッティイメージズ日曜日の夜、ダンサー、振付師、女優のカルメンデラヴァラードが第40回ケネディセンター名誉賞を受賞しました。今年は、ドナルドトランプ首長のクレチンが祝福されていないことで、この式典がさらに注目を集めました。まだ見事な86歳のとき、伝説的なパフォーマーであるde Lavalladeは失望せず、真の優雅さと美しさが時代を超えていることを示しました。

ファイナルファンタジーXVのマルチプレイヤーは少量でとても楽しいです

ファイナルファンタジーXVのマルチプレイヤーは少量でとても楽しいです

くそー、私はちょうどこのシャツを買いました。一部の人にとっては、ファイナルファンタジーXVのマルチプレイヤー拡張パックは、スクウェア・エニックスの壮大なRPGを友達と体験するための面白い(少しイライラする場合でも)方法です。

ナズは面会権をめぐってケリスを法廷に連れて行く

ナズは面会権をめぐってケリスを法廷に連れて行く

ナズとケリス(ローレンス・ルシエ/ゲッティイメージズ)ナズは息子とより多くの時間を過ごしたいと考えており、現在、元妻のケリスを正式な面会スケジュールのために法廷に連れて行っています。ブラストが入手した文書によると、ナズは彼がは「長年にわたってケリスと協力して働いてきた」が、ケリスは「彼女が自分にとって都合がよいと判断した場合にのみ、息子との監護権を行使することを許可している。

ケイト・ミドルトンとウィリアム王子は、彼らが子供たちと行っているスパイをテーマにした活動を共有しています

ケイト・ミドルトンとウィリアム王子は、彼らが子供たちと行っているスパイをテーマにした活動を共有しています

ケイト・ミドルトンとウィリアム王子は、子供向けのパズルの本の序文を書き、ジョージ王子、シャーロット王女、ルイ王子と一緒にテキストを読むと述べた.

事故で押しつぶされたスイカは、動物を喜ばせ水分補給するために野生生物保護団体に寄付されました

事故で押しつぶされたスイカは、動物を喜ばせ水分補給するために野生生物保護団体に寄付されました

Yak's Produce は、数十個のつぶれたメロンを野生動物のリハビリ専門家であるレスリー グリーンと彼女のルイジアナ州の救助施設で暮らす 42 匹の動物に寄付しました。

デミ・ロヴァートは、新しいミュージシャンのボーイフレンドと「幸せで健康的な関係」にあります: ソース

デミ・ロヴァートは、新しいミュージシャンのボーイフレンドと「幸せで健康的な関係」にあります: ソース

8 枚目のスタジオ アルバムのリリースに向けて準備を進めているデミ ロヴァートは、「スーパー グレート ガイ」と付き合っている、と情報筋は PEOPLE に確認しています。

Plathville の Kim と Olivia Plath が数年ぶりに言葉を交わすことへようこそ

Plathville の Kim と Olivia Plath が数年ぶりに言葉を交わすことへようこそ

イーサン プラスの誕生日のお祝いは、TLC のウェルカム トゥ プラスビルのシーズン 4 のフィナーレで、戦争中の母親のキム プラスと妻のオリビア プラスを結びつけました。

仕事の生産性を高める 8 つのシンプルなホーム オフィスのセットアップのアイデア

仕事の生産性を高める 8 つのシンプルなホーム オフィスのセットアップのアイデア

ホームオフィスのセットアップ術を極めよう!AppExert の開発者は、家族全員が一緒にいる場合でも、在宅勤務の技術を習得しています。祖父や曽祖父が共同家族で暮らしていた頃の記憶がよみがえりました。

2022 年、私たちのデジタル ライフはどこで終わり、「リアル ライフ」はどこから始まるのでしょうか?

20 年前のタイムトラベラーでさえ、日常生活におけるデジタルおよびインターネットベースのサービスの重要性に驚くことでしょう。MySpace、eBay、Napster などのプラットフォームは、高速化に焦点を合わせた世界がどのようなものになるかを示してくれました。

ニューロマーケティングの秘密科学

ニューロマーケティングの秘密科学

マーケティング担当者が人間の欲望を操作するために使用する、最先端の (気味が悪いと言う人もいます) メソッドを探ります。カートをいっぱいにして 3 桁の領収書を持って店を出る前に、ほんの数点の商品を買いに行ったことはありませんか? あなたは一人じゃない。

地理情報システムの日: GIS 開発者として学ぶべき最高の技術スタック

地理情報システムの日: GIS 開発者として学ぶべき最高の技術スタック

私たちが住んでいる世界を確実に理解するには、データが必要です。ただし、空間参照がない場合、このデータは地理的コンテキストがないと役に立たなくなる可能性があります。

Language