配列をオブジェクトに変換


514

変換する最良の方法は何ですか:

['a','b','c']

に:

{
  0: 'a',
  1: 'b',
  2: 'c'
}

3
多分彼が必要としているのは、それが配列インスタンスであると考えないいくつかのダックタイピングコードです
ポイティ

6
Javascript配列オブジェクトであることを指摘する価値はあります。
Spudley、2010年

他の誰かがLodashソリューションを探している場合は、_.keyBy(以前は_.indexBy)検討してください:lodash.com/docs#keyBy
2540625

配列はすでにオブジェクトであるため、これは少し混乱しますが、問題は、配列の エキゾチックなオブジェクト通常のオブジェクトに変換することです。
Oriol

1
Lodashでこれを行う簡単な方法は_.toPlainObjectです。例:var myObj = _.toPlainObject(myArr)
Julian Soro

回答:


473

ECMAScript 6は簡単にポリフィル可能なものを導入しますObject.assign

このObject.assign()メソッドは、列挙可能なすべての独自のプロパティの値を1つ以上のソースオブジェクトからターゲットオブジェクトにコピーするために使用されます。ターゲットオブジェクトを返します。

Object.assign({}, ['a','b','c']); // {0:"a", 1:"b", 2:"c"}

length配列の独自のプロパティは列挙できないため、コピーされません。

また、ES6 スプレッド構文を使用して同じ結果を得ることができます。

{ ...['a', 'b', 'c'] }

ただ、指摘したい-あなたはすでに使用して、元のオブジェクトからソートされたプロパティの配列を持っている場合は、拡散演算子を新しいオブジェクトに直接その配列を向けるだろう何をされています{ ...[sortedArray]}
HappyHands31

オリオール、0&1の代わりに固定キーを設定する方法はありますか?
Menai Ala Eddine

488

このような関数を使って:

function toObject(arr) {
  var rv = {};
  for (var i = 0; i < arr.length; ++i)
    rv[i] = arr[i];
  return rv;
}

配列はすでにほぼオブジェクトにすぎませんが、配列には整数名付きプロパティに関して「興味深い」特別な動作があります。上記は単純なオブジェクトを提供します。

編集はああも、あなたは、アレイ内の「穴」のアカウントが必要になる場合があります

function toObject(arr) {
  var rv = {};
  for (var i = 0; i < arr.length; ++i)
    if (arr[i] !== undefined) rv[i] = arr[i];
  return rv;
}

最新のJavaScriptランタイムでは、次の.reduce()メソッドを使用できます。

var obj = arr.reduce(function(acc, cur, i) {
  acc[i] = cur;
  return acc;
}, {});

これは、配列内の「穴」も回避するためです.reduce()


2
@ m93aそれはすでにオブジェクトです。JavaScriptでは、[]数値プロパティキーと「length」プロパティを使用しない場合は、Arrayインスタンス()を作成しても意味がありません。
先のとがった

14
パラメータの再割り当てを回避するためのよりクリーンな方法const obj = arr.reduce((obj, cur, i) => { return { ...obj, [i]: cur }; }, {});
huygn 2017年

3
矢印+明示的な戻り値のない構文の構文:const obj = arr.reduce((obj, cur, i) => ({ ...obj, [i]: cur }), {});
Marc Scheib

2
@eugene_sunic確かに、しかし2010年に私がこれに答えたとき、そのアプローチは利用できませんでした:)
Pointy

2
@miroが指摘するように、毎回新しいオブジェクトを作成する必要はなく、実際は、作成された最初のオブジェクトを操作するよりはるかに遅くなります。1000要素の配列でJSPerfテストを実行し、毎回新しいオブジェクトを作成すると、既存のオブジェクトを変更するよりも1,000倍遅くなります。jsperf.com/...
romellem

281

アキュムレータakaを使用できますreduce

['a','b','c'].reduce(function(result, item, index, array) {
  result[index] = item; //a, b, c
  return result;
}, {}) //watch out the empty {}, which is passed as "result"

空のオブジェクト{}を開始点として渡します。次に、そのオブジェクトを段階的に「拡張」します。反復の終わりには、resultなります{"0": "a", "1": "b", "2": "c"}

配列がキーと値のペアのオブジェクトのセットである場合:

[{ a: 1},{ b: 2},{ c: 3}].reduce(function(result, item) {
  var key = Object.keys(item)[0]; //first property: a, b, c
  result[key] = item[key];
  return result;
}, {});

生成されます: {a: 1, b: 2, c: 3}

完全をreduceRight期すために、配列を逆の順序で反復できるようにします。

[{ a: 1},{ b: 2},{ c: 3}].reduceRight(/* same implementation as above */)

生成されます: {c:3, b:2, a:1}

アキュムレータは、特定の目的のために任意のタイプにすることができます。たとえば、配列内のオブジェクトのキーと値を交換するには、次を渡し[]ます:

[{ a: 1},{ b: 2},{ c: 3}].reduce(function(result, item, index) {
  var key = Object.keys(item)[0]; //first property: a, b, c
  var value = item[key];
  var obj = {};
  obj[value] = key;
  result.push(obj);
  return result;
}, []); //an empty array

生成されます: [{1: "a"}, {2: "b"}, {3: "c"}]

とは異なりmapreduce1-1マッピングとして使用することはできません。含めるまたは除外するアイテムを完全に制御できます。したがってreduce、あなたは何をするかを達成することfilterができ、それはreduce非常に用途が広いです:

[{ a: 1},{ b: 2},{ c: 3}].reduce(function(result, item, index) {
  if(index !== 0) { //skip the first item
    result.push(item);
  }
  return result;
}, []); //an empty array

生成されます: [{2: "b"}, {3: "c"}]

注意reduceおよびのObject.key一部ですECMA 5th edition。それらをサポートしないブラウザー(特にIE8)にはポリフィルを提供する必要があります。

Mozillaによるデフォルトの実装をご覧ください。


1
オブジェクトのマップを使用していて、キーの1つをドロップする必要がある場合に、reduxストアの保守に
役立ち

101

jqueryを使用している場合:

$.extend({}, ['a', 'b', 'c']);

4
奇妙なことに、配列変数を指定すると、すべての文字が個別のオブジェクトに配置されます。 。
TrySpace

@Maxそのような振る舞いはないと思います。返されるオブジェクトは{0: 'a', 1: 'b', 2: 'c'}、期待される結果です。
ivkremer 2013年

3
$ .extendを使用しながら、キーを非数値的な方法で通知する方法はありますか。
Davi Lima

超素晴らしく短いテスト
ファイサルメフムードアワン

63

完全を期すために、ECMAScript 2015(ES6)の普及。transpiler(Babel)または少なくともES6を実行している環境が必要です。

console.log(
   { ...['a', 'b', 'c'] }
)


2
実際、これはES2015でもネイティブで利用できません。しかし、それは非常にエレガントです。
Aluan Haddad

47

私はおそらくそれをこのように書くでしょう(非常にまれに、私はunderscorejsライブラリを手元に置いていないからです):

var _ = require('underscore');

var a = [ 'a', 'b', 'c' ];
var obj = _.extend({}, a);
console.log(obj);
// prints { '0': 'a', '1': 'b', '2': 'c' }

9
あなたは私の回答に反対票を投じますが、コメントはありませんか?私の答えは正しく、テストされています。異議は何ですか?
Dave Dopson、2013年

14
この質問にはアンダースコアタグがなく、node.jsまたはrequireライブラリも想定しています。
David Hellsing

10
下線はクライアントとサーバーの両方でかなり一般的です。これはBackbone.jsを想定しており、おそらく最も一般的なユーティリティライブラリです。そうは言っても、ライブラリを使用していることを明確にするためにrequire行を含めました。「ページにunderscore.jsを追加する」を説明するための1行はありません。そのため、ブラウザ環境ではある程度の翻訳が必要です
Dave Dopson

6
それでも、undserscoreを使用している場合は、シンプルで十分ですobj=_.extend({},a);。また、配列を反復処理する場合_.eachは、より適切だと思います_.map。全体として、これはいくつかのレベルで良い答えではありません。
David Hellsing

4
「アンダースコアやローダッシュに言及せずに答えなければならない」という人はとてもうんざりします。標準ライブラリに言及せずにC ++の質問に答える必要があると言うのに匹敵します。アンダースコアまたはローダッシュがオプションではない場合、OPはそれを言及する必要があります。
チャーリーマーティン

26

以下は、完全を期すためのO(1)ES2015メソッドです。

var arr = [1, 2, 3, 4, 5]; // array, already an object
Object.setPrototypeOf(arr, Object.prototype); // now no longer an array, still an object

(1)MDNによれば、オブジェクトの[[Prototype]]の変更は非常に遅い操作です。(2)これは自身のlengthプロパティを削除しません。(3)オブジェクトはまだ配列ですArray.isArray(arr) === true。(4)arr.length = 0すべてのインデックスを削除するなど、特別な配列動作は削除されません。(5)したがって、私Object.assignははるかに優れていると思います
Oriol

1
@Oriol mdnは間違っています。少なくともV8では(ただし他のエンジンでも)、これはこの特定のケースではかなり高速な操作です。オブジェクトに数値ストアがあるため、これは基本的に2つのポインタを変更します。
Benjamin Gruenbaum 2016年

これは、他のクイックソリューションの中で明らかにユニークであるという事実にも使用できます。つまり、配列のインデックス以外の(「独自の」)プロパティ(つまり、正でない整数のプロパティ)を保持します...
Brett Zamir

しかし、うーん、ここでは "オブジェクト"をArray.isArray返さないのに...trueinstanceof Array
Brett Zamir

バグのように聞こえる@BrettZamir:D
Benjamin

26

見ていないことに驚いた-

console.log(
  Object.assign({}, ['a', 'b', 'c'])
)


{ "first":"a", "second":"b","third":"c" }修正されたキーを使用して作成するスマートな提案-私は破壊を探しています
mplungjan

@mplungjanその場合、割り当ての代わりに削減を使用することをお勧めします。おそらく、必要に応じてすべての序数を列挙できるライブラリがあります。
Wylliam Judd

今日も別の症例がありました。:私はそれについての質問を尋ねることになったstackoverflow.com/questions/62197270/destruct-using-titles/...
mplungjanを

23

我々は使用することができますObject.assignし、array.reduceオブジェクトの配列を変換する機能。

var arr = [{a:{b:1}},{c:{d:2}}] 
var newObj = arr.reduce((a, b) => Object.assign(a, b), {})

console.log(newObj)


これは私が探していたものです。索引は必要ありませんでした。配列を保持されたキーと値のペアに変換する必要がありました。
Mike K

18

ECMAScript 2015(ES6)標準の一部であるため、オブジェクトスプレッドオペレーターを使用しました。

const array = ['a', 'b', 'c'];
console.log({...array});
// it outputs {0:'a', 1:'b', 2:'c'}

例として次のフィドルを作成しました。


1
これのパフォーマンスについてはわかりませんが、配列からオブジェクトへの変換の数が多いため(すべてのコードでオブジェクトを使用して標準化したいため)、おそらくこれが最も簡単です。
誰か特別な

これは、まったく同じソリューションを提供する既存の回答のどれよりも優れていますか?
Dan Dascalescu

17
Object.assign({}, ['one', 'two']); // {0: 'one', 1: 'two'}

最近のJavaScriptでの簡単な方法はObject.assign()、あるオブジェクトから別のオブジェクトにkey:valueをコピーする以外に何もしないことです。この例でArrayは、プロパティをnew に寄付します{}


これは、まったく同じソリューションを提供する既存の回答のどれよりも優れていますか?
Dan Dascalescu

Dan Dascalescuが私が回答を追加したときに、上記の回答しかありませんO.assignでしたが、説明が不足していました。現在、配列をオブジェクトに{...array}
分解する

14

ES2016の場合、オブジェクトの演算子を展開します。注:これはES6のであるため、トランスパイラーを調整する必要があります。

const arr = ['a', 'b', 'c'];
const obj = {...arr}; // -> {0: "a", 1: "b", 2: "c"} 


スプレッドオペレーターの回答は、2年前にすでに与えられてます。
Dan Dascalescu


10

これ javascript#forEachを行うことができます

var result = {},
    attributes = ['a', 'b','c'];

attributes.forEach(function(prop,index) {
  result[index] = prop;
});

ECMA6の場合:

attributes.forEach((prop,index)=>result[index] = prop);

10

FWIWは、お互いの最近のアプローチは、新しいを使用することであるObject.fromEntriesとともにObject.entries、次のように:

const arr = ['a','b','c'];
arr[-2] = 'd';
arr.hello = 'e';
arr.length = 17;
const obj = Object.fromEntries(Object.entries(arr));

...まばらな配列項目をundefinedまたはとして保存することを避けることができますnull、非インデックス(例:非正整数/非数値)キーを保持します。

arr.lengthただし、は含まれていないため、を追加することもできます。

obj.length = arr.length;


9

ES6を使用している場合は、Object.assignとspread演算子を使用できます

{ ...['a', 'b', 'c'] }

あなたがのような配列を入れ子にしている場合

var arr=[[1,2,3,4]]
Object.assign(...arr.map(d => ({[d[0]]: d[1]})))

1
変数名が異なるだけでなく、例も機能しません。コンストラクターからマップを作成するには、最初に2Dキー値配列が必要です。new Map([['key1', 'value1'], ['key2', 'value2']]);
Shannon Hochkins

5

素早く汚いもの:

var obj = {},
  arr = ['a','b','c'],
  l = arr.length; 

while( l && (obj[--l] = arr.pop() ) ){};

あなたはそれをテストするのを忘れたと思います。それは作り出す{0:"c", 1:"b", 2:"a"}。あなたは、どちらかの希望unshiftの代わりに、popまたは(より良い)で始まりi=arr.length-1、代わりにデクリメント。
Phrogz、2010年

ええ..変更しただけですが、面白くなくなりました:/
Mic

することもできますl = arr.length(そして、while (l && (obj[--l] = arr.pop())){}これは古いことに気づきますが、さらに単純化しないでください)。
Qix-モニカは2015

2
@Qix、ニースショートニング
マイク

4

速くて汚い#2:

var i = 0
  , s = {}
  , a = ['A', 'B', 'C'];

while( a[i] ) { s[i] = a[i++] };

なぜカンマ表記を使用しているのですか?
Conner Ruhl、2013年

3
次の行にコンマを付けるのは個人的な好みです。この表記は読みやすいと思います。
BingeBoy 2013年

1
配列に偽の値が含まれている場合、ループは停止します。のi < a.length代わりにチェックする必要がありa[i]ます。
Oriol

4

Lodash 3.0.0のとおり、あなたは使用することができます_.toPlainObjectを

var obj = _.toPlainObject(['a', 'b', 'c']);
console.log(obj);
<script src="https://cdn.jsdelivr.net/lodash/4.16.4/lodash.min.js"></script>


3

これが私が書いたばかりの再帰関数です。シンプルでうまく機能します。

// Convert array to object
var convArrToObj = function(array){
    var thisEleObj = new Object();
    if(typeof array == "object"){
        for(var i in array){
            var thisEle = convArrToObj(array[i]);
            thisEleObj[i] = thisEle;
        }
    }else {
        thisEleObj = array;
    }
    return thisEleObj;
}

次に例を示します(jsFiddle):

var array = new Array();
array.a = 123;
array.b = 234;
array.c = 345;
var array2 = new Array();
array2.a = 321;
array2.b = 432;
array2.c = 543;
var array3 = new Array();
array3.a = 132;
array3.b = 243;
array3.c = 354;
var array4 = new Array();
array4.a = 312;
array4.b = 423;
array4.c = 534;
var array5 = new Array();
array5.a = 112;
array5.b = 223;
array5.c = 334;

array.d = array2;
array4.d = array5;
array3.d = array4;
array.e = array3;


console.log(array);

// Convert array to object
var convArrToObj = function(array){
    var thisEleObj = new Object();
    if(typeof array == "object"){
        for(var i in array){
            var thisEle = convArrToObj(array[i]);
            thisEleObj[i] = thisEle;
        }
    }else {
        thisEleObj = array;
    }
    return thisEleObj;
}
console.log(convArrToObj(array));

結果: オブジェクトへの再帰的な配列


本当にうまくいきます。ありがとう
Hanmaslah 2017年

あなたが持っていて['a' = '1', 'b' = '2', 'c' = '3']{a: 1, b: 2, c: 3}このようにそれが完璧に機能することを望むならば、これはより高いはずです。
Wanjia 2017

3
.reduce((o,v,i)=>(o[i]=v,o), {})

[ドキュメント]

以上の冗長

var trAr2Obj = function (arr) {return arr.reduce((o,v,i)=>(o[i]=v,o), {});}

または

var transposeAr2Obj = arr=>arr.reduce((o,v,i)=>(o[i]=v,o), {})

バニラJSで最短のもの

JSON.stringify([["a", "X"], ["b", "Y"]].reduce((o,v,i)=>{return o[i]=v,o}, {}))
=> "{"0":["a","X"],"1":["b","Y"]}"

より複雑な例

[["a", "X"], ["b", "Y"]].reduce((o,v,i)=>{return o[v[0]]=v.slice(1)[0],o}, {})
=> Object {a: "X", b: "Y"}

さらに短い(function(e) {console.log(e); return e;}=== を使用(e)=>(console.log(e),e)

 nodejs
> [[1, 2, 3], [3,4,5]].reduce((o,v,i)=>(o[v[0]]=v.slice(1),o), {})
{ '1': [ 2, 3 ], '3': [ 4, 5 ] }

[/ドキュメント]


あなたは何を意図しました[/docs]か?コードスニペットを実行可能にする方が便利です。
Dan Dascalescu

3

これは単にで行いArray.of()ます。配列には、そのコンテキストをコンストラクターとして使用する機能があります。

注2 of関数は、意図的に汎用的なファクトリメソッドです。この値がArrayコンストラクタである必要はありません。したがって、単一の数値引数で呼び出すことができる他のコンストラクターに転送または継承できます。

したがってArray.of()、関数にバインドして、オブジェクトのような配列を生成できます。

function dummy(){};
var thingy = Array.of.apply(dummy,[1,2,3,4]);
console.log(thingy);

利用するArray.of() ことで、配列のサブクラス化を行うことさえできます。


3

Mapまたはを使用できる場合Object.assign、それは非常に簡単です。

配列を作成します。

const languages = ['css', 'javascript', 'php', 'html'];

以下は、インデックスをキーとして持つオブジェクトを作成します:

Object.assign({}, languages)

上記と同じをマップで複製

インデックスベースのオブジェクト{0 : 'css'}などに変換します。

const indexMap = new Map(languages.map((name, i) => [i, name] ));
indexMap.get(1) // javascript

値ベースのオブジェクト{css : 'css is great'}などに変換します...

const valueMap = new Map(languages.map(name => [name, `${name} is great!`] ));
valueMap.get('css') // css is great

3

アイテムの配列をオブジェクトにすばやく変換するシンプルで生意気な方法

function arrayToObject( srcArray ){
    return  JSON.parse( JSON.stringify( srcArray ) );
}

次に、それをそのように使用します...

var p = [0,2,3,'pork','pie',6];
obj = new arrayToObject( p );
console.log( obj[3], obj[4] )
// expecting `pork pie`

出力:

pork pie

タイプの確認:

typeof obj
"object"

そして、プロトタイプメソッドがなければ、物事は完全ではありません。

Array.prototype.toObject =function(){
    return  JSON.parse( JSON.stringify( this ) );
}

ライクの使用:

var q = [0,2,3,'cheese','whizz',6];
obj = q.toObject();
console.log( obj[3], obj[4] )
// expecting `cheese whizz`

出力:

cheese whizz

*名前付けルーチンがないことに注意してください。したがって、特定の名前を付けたい場合は、以下の既存のメソッドを引き続き使用する必要があります。


古い方法

これにより、定義したキーを必要な順序で使用して、配列からオブジェクトを生成できます。

Array.prototype.toObject = function(keys){
    var obj = {};
    var tmp = this; // we want the original array intact.
    if(keys.length == this.length){
        var c = this.length-1;
        while( c>=0 ){
            obj[ keys[ c ] ] = tmp[c];
            c--;
        }
    }
    return obj;
};

result = ["cheese","paint",14,8].toObject([0,"onion",4,99]);

console.log(">>> :" + result.onion); 「ペイント」を出力します。関数は同じ長さの配列を持っている必要があります。

ここに更新されたメソッドがあります

Array.prototype.toObject = function(keys){
    var obj = {};
    if( keys.length == this.length)
        while( keys.length )
            obj[ keys.pop() ] = this[ keys.length ];
    return obj;
};

これにより、キー配列の内容と、内部コメントにもかかわらず値配列(その内容)の両方が破棄されます。JavaScriptの動作はPHPとは異なり、JavaScriptはオブジェクト/配列のプロパティの参照によって自動的に動作します。
Brett Zamir

いいえ、そうではありません。ルーチンはコピーを作成し、オリジナルには触れません。
マークギブリン2014

はい、オリジナルに触れました。jsfiddle.net/bRTv7を参照してください。配列の長さは、両方が0になってしまう
ブレットザミール

OK、私が変更したばかりの編集済みバージョンは配列を破壊しません。それを行うべきだったのに奇妙なことに気づきます。
マークギブリン2014

1
JSONはECMAが追加した新しいコード機能よりもずっと古いため、古いブラウザーでサポートされるべき更新されたメソッド
Mark Giblin

2

let i = 0;
let myArray = ["first", "second", "third", "fourth"];

const arrayToObject = (arr) =>
    Object.assign({}, ...arr.map(item => ({[i++]: item})));

console.log(arrayToObject(myArray));

または使用

myArray = ["first", "second", "third", "fourth"]
console.log({...myArray})


2

ES5-ソリューション:

使用するアレイプロトタイプ機能「プッシュ」をして「適用」あなたは、配列の要素を持つオブジェクトを移入することができます。

var arr = ['a','b','c'];
var obj = new Object();
Array.prototype.push.apply(obj, arr);
console.log(obj);    // { '0': 'a', '1': 'b', '2': 'c', length: 3 }
console.log(obj[2]); // c


変換したい場合{ name: a, div :b, salary:c}
Prashant Pimpale

2

より多くのブラウザーがサポートされそれを行うためのより柔軟な方法は、次のような通常のループを使用することです:

const arr = ['a', 'b', 'c'],
obj = {};

for (let i=0; i<arr.length; i++) {
   obj[i] = arr[i];
}

しかし、最近の方法では、次のように、spread演算子を使用することもできます。

{...arr}

またはオブジェクトの割り当て

Object.assign({}, ['a', 'b', 'c']);

両方が返されます:

{0: "a", 1: "b", 2: "c"}

1

次のような関数を使用できます。

var toObject = function(array) {
    var o = {};
    for (var property in array) {
        if (String(property >>> 0) == property && property >>> 0 != 0xffffffff) {
            o[i] = array[i];
        }
    }
    return o;
};

これは、スパース配列をより効率的に処理する必要があります。


1

これがcoffeescriptの解決策です

arrayToObj = (arr) ->
  obj = {}
  for v,i in arr
    obj[i] = v if v?
  obj

7
coffeescriptとは何ですか?私たちはJSについて話している!:D
m93a 2013年

2
JavaScriptにコンパイルされる小さな言語です:)
David

6
フン、それは奇妙な表記法を使用しています。私は普通のJSがもっと好きです。
m93a

2
@David 1行でforループ全体を実行して、全体を3行だけにすることができます。:)例obj[i] = v for v,i in arr when v?
XåpplI'-I0llwlg'I -
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.