web-dev-qa-db-fra.com

Convertir un tableau en objet

Quel est le meilleur moyen de convertir:

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

à:

{
  0: 'a',
  1: 'b',
  2: 'c'
}
343
David Hellsing

ECMAScript 6 introduit le Object.assign : facilement polyfillable

La méthode Object.assign() est utilisée pour copier les valeurs de tous propriétés énumérables propres d'un ou plusieurs objets source à une cible objet. Il retournera l'objet cible.

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

La propriété propre length du tableau n'est pas copiée car elle n'est pas énumérable.

De plus, vous pouvez utiliser ES6 propagation syntaxe pour obtenir le même résultat:

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

Avec une fonction comme celle-ci:

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

Votre tableau est déjà plus ou moins juste un objet, mais les tableaux ont un comportement "intéressant" et spécial en ce qui concerne les propriétés nommées par un entier. Ce qui précède vous donnera un objet simple.

edit oh aussi vous voudrez peut-être rendre compte des "trous" dans le tableau:

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

Dans les exécutions JavaScript modernes, vous pouvez utiliser la méthode .reduce():

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

Celui-ci évite également les "trous" dans le tableau, car c'est ainsi que fonctionne .reduce().

424
Pointy

Vous pouvez utiliser un accumulateur 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"

Passez un objet vide {} comme point de départ; puis "augmente" progressivement cet objet . À la fin des itérations, result sera {"0": "a", "1": "b", "2": "c"}

Si votre tableau est un ensemble d'objets paire paire clé-valeur:

[{ 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;
}, {});

produira: {a: 1, b: 2, c: 3}

Par souci d'exhaustivité, reduceRight vous permet de parcourir votre tableau dans l'ordre inverse:

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

produira: {c:3, b:2, a:1}

Votre accumulateur peut être de tout type pour un but spécifique. Par exemple, pour échanger la clé et la valeur de votre objet dans un tableau, transmettez []:

[{ 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

produira: [{1: "a"}, {2: "b"}, {3: "c"}]

Contrairement à map, reduce ne peut pas être utilisé comme mappage 1-1. Vous avez un contrôle total sur les éléments que vous souhaitez inclure ou exclure. Donc, reduce vous permet d’atteindre ce que filter fait, ce qui rend reduce très polyvalent:

[{ 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

produira: [{2: "b"}, {3: "c"}]

Caution: reduce et Object.key font partie de ECMA 5th edition; vous devriez fournir un polyfill aux navigateurs qui ne les prennent pas en charge (notamment IE8).

Voir une implémentation par défaut de Mozilla .

217
roland

Si vous utilisez jQuery:

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

Pour être complet, ECMAScript 2015 (ES6) spreading. Nécessite un transpiler (Babel) ou un environnement exécutant au moins ES6.

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

Je l’écrirais probablement de cette façon (car très rarement je n’aurai pas la bibliothèque underscorejs sous la main):

var _ = require('underscore');

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

Voici une méthode O(1) ES2015 juste pour être complet.

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

Surpris de ne pas voir -

Object.assign({}, your_array)
20
Wylliam Judd
Object.assign({}, ['one', 'two']); // {0: 'one', 1: 'two'}

La méthode la plus simple en JavaScript moderne consiste à utiliser Object.assign() qui ne copie que la clé: valeur d’un objet à un autre. Dans notre cas, Array donne des propriétés au nouveau {}.

16
Appeiron

J'ai fini par utiliser l'opérateur de propagation d'objet, car il fait partie de la norme ECMAScript 2015 (ES6).

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

Fait le suivant violon à titre d'exemple.

15
locropulenton

nous pouvons utiliser les fonctions Object.assign et array.reduce pour convertir un tableau en objet .

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

console.log(newObj)

13
KARTHIKEYAN.A

Cinq ans plus tard, il y a un bon moyen :)

Object.assign a été introduit dans ECMAScript 2015.

Object.assign({}, ['a', 'b', 'c'])
// {'0':'a', '1':'b', '2':'c'}
9
Paul Draper

vous pouvez utiliser l'opérateur spread

x = [1,2,3,10]
{...x} // {0:1, 1:2, 2:3, 3:10}
8
noel zubin

Un rapide et sale:

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

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

En utilisant la syntaxe ES6 vous pouvez faire quelque chose comme:

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

5
Oleksii Trekhleb

En utilisant javascript#forEach on peut le faire

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

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

Avec ECMA6:

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

Depuis Lodash 3.0.0, vous pouvez utiliser _.toPlainObject

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

4
acontell

Si vous utilisez ES6, vous pouvez utiliser Object.assign et l'opérateur spread.

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

Si vous avez un tableau imbriqué comme

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

Rapide et sale # 2:

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

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

Je le ferais simplement avec Array.of(). Array of a la capacité d'utiliser son contexte en tant que constructeur.

NOTE 2 La fonction of est une méthode d'usine intentionnellement générique; il ne nécessite pas que sa cette valeur soit le constructeur Array . Par conséquent, il peut être transféré ou hérité par d'autres constructeurs qui peut être appelé avec un seul argument numérique.

Donc, nous pouvons lier Array.of() à une fonction et générer un tableau comme objet.

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

En utilisant Array.of()on peut même faire un sous-classement de tableaux .

3
Redu

Voici une fonction récursive que je viens d'écrire. C'est simple et fonctionne bien.

// 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;
}

Voici un exemple ( 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));

Résultats:Recursive Array to Object

2
JVE999

Voici une solution en coffeescript

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

Cela vous permet de générer à partir d'un tableau un objet avec les clés que vous définissez dans l'ordre de votre choix. 

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); affichera "Paint", la fonction doit avoir des tableaux de longueur égale ou vous obtenez un objet vide.

Voici une méthode mise à jour

Array.prototype.toObject = function(keys){
    var obj = {};
    if( keys.length == this.length)
        while( keys.length )
            obj[ keys.pop() ] = this[ keys.length ];
    return obj;
};
2
Mark Giblin
.reduce((o,v,i)=>(o[i]=v,o), {})

[docs]

ou plus verbeux

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

ou

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

le plus court avec Vanilla JS

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

un exemple plus complexe

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

encore plus court (en utilisant 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]

2
test30

Si vous utilisez angularjs, vous pouvez utiliser angular.extend, le même effet avec $ .extend of jquery.

var newObj = {};
angular.extend(newObj, ['a','b','c']);
2
Vicruz

Si vous pouvez utiliser Map ou Object.assign, c'est très simple.

Créer un tableau:

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

La création ci-dessous crée un objet avec index en tant que clé:

Object.assign({}, languages)

Répliquer la même chose que ci-dessus avec Maps

Conversion en objet basé sur l'index {0 : 'css'} etc ...

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

Convertir en un objet basé sur la valeur {css : 'css is great'} etc ...

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

Vous pouvez utiliser une fonction comme celle-ci:

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;
};

Celui-ci devrait gérer les tableaux clairsemés plus efficacement.

1
Pablo Cabrera

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

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

console.log(arrayToObject(myArray));

Ou utiliser

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

1
Mahdi Bashirpour

Ce n’est pas directement pertinent, mais je suis venu ici à la recherche d’une couche unique pour la fusion d’objets imbriqués tels que 

const nodes = {
    node1: {
        interfaces: {if1: {}, if2: {}}
    },
    node2: {
        interfaces: {if3: {}, if4: {}}
    },
    node3: {
        interfaces: {if5: {}, if6: {}}
    },
}

La solution consiste à utiliser une combinaison de réduction et de propagation d'objet:

const allInterfaces = nodes => Object.keys(nodes).reduce((res, key) => ({...res, ...nodes[key].interfaces}), {})
1
Adnan Y

J'ai fait face à ce problème plusieurs fois et j'ai décidé d'écrire une fonction aussi générique que possible. Regardez et n'hésitez pas à modifier quoi que ce soit

function typeOf(obj) {
    if ( typeof(obj) == 'object' ) {
        if (obj.length)
            return 'array';
        else
            return 'object';
    } else
    return typeof(obj);
}

function objToArray(obj, ignoreKeys) {
    var arr = [];
    if (typeOf(obj) == 'object') {
        for (var key in obj) {
            if (typeOf(obj[key]) == 'object') {
                if (ignoreKeys)
                    arr.Push(objToArray(obj[key],ignoreKeys));
                else
                    arr.Push([key,objToArray(obj[key])]);
            }
            else
                arr.Push(obj[key]);
        }
    }else if (typeOf(obj) == 'array') {
        for (var key=0;key<obj.length;key++) {
            if (typeOf(obj[key]) == 'object')
                arr.Push(objToArray(obj[key]));
            else
                arr.Push(obj[key]);
        }
    }
    return arr;
}
0
Mohamed El Harty

Utilisez la bibliothèque javascript lodash. Il existe une méthode simple _.mapKeys(object, [iteratee=_.identity]) cela peut faire la conversion. 

0
ugwu jude

J'utiliserais un trait de soulignement pour cela, mais si cela n'était pas disponible, j'utiliserais réduire avec une valeur initiale d'objet vide {}

>>> ['a', 'b', 'c'].reduce(function(p, c, i) {p[i] = c; return p}, {})
Object { 0="a", 1="b", 2="c"}

réduire devrait être largement disponible dans la plupart des navigateurs aujourd'hui, voir MDN

0
Meitham

Plus de navigateur pris en charge consiste à utiliser une boucle normale, quelque chose comme:

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

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

Mais la manière moderne pourrait aussi utiliser le opérateur de propagation, comme:

{...arr}

Ou attribution d'objet:

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

Les deux vont retour:

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

Il est facile d’utiliser javascript réduire:

["a", "b", "c", "d"].reduce(function(previousValue, currentValue, index) { 
   previousValue[index] = currentValue; 
   return previousValue;
}, 
{}
);

Vous pouvez consulter Array.prototype.reduce (), https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

0
Ping.Goblue

FWIW, une autre approche récente consiste à utiliser le nouveau Object.fromEntries avec Object.entries comme suit:

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

... qui permet d'éviter de stocker des éléments de tableau fragmentés sous la forme undefined ou null et de conserver les clés non indexées (par exemple, les entiers non positifs/non numériques).

On peut souhaiter ajouter arr.length, cependant, car cela n’est pas inclus:

obj.length = arr.length;
0
Brett Zamir

ES5 - Solution:

En utilisant Array fonction prototype 'Push' et 'apply' vous pouvez remplir l'objet avec les éléments du tableau.

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

0
SridharKritha

tableau initial et convertira en un objet avec des clés qui sera l’élément unique d’un tableau et la valeur de la clé sera le nombre de répétitions

var jsTechs = ['angular', 'react', 'ember', 'vanilaJS', 'ember', 'angular', 'react', 'ember', 'vanilaJS', 'angular', 'react', 'ember', 'vanilaJS', 'ember', 'angular', 'react', 'ember', 'vanilaJS', 'ember', 'angular', 'react', 'ember', 'vanilaJS', 'ember', 'react', 'react', 'vanilaJS', 'react', 'vanilaJS', 'vanilaJS']

var initialValue = {
  Java : 4
}

var reducerFunc = function reducerFunc (initObj, jsLib) {
  if (!initObj[jsLib]) {
    initObj[jsLib] = 1
  } else {
    initObj[jsLib] += 1
  }
  return initObj
}
var finalResult = jsTechs.reduce(reducerFunc, initialValue)
console.log(finalResult)

0
bvmCoder

La méthode ci-dessous convertirait un tableau en objet avec une clé donnée.

    /**
     * Converts array to object
     * @param  {Array} array
     * @param  {string} key (optional)
     */
    Array.prototype.ArrayToObject = function(key) {
       const array = this;
       const obj = {};

       array.forEach((element, index) => {
           if(!key) {
              obj[index] = element;
           } else if ((element && typeof element == 'object' && element[key])) {
              obj[element[key]] = element;
           }
       });
    return obj;
    }

Pour Ex -

[{name: 'test'}, {name: 'test1'}]. ArrayToObject ('name');

donnerait 

{test: {name: 'test'}, test1: {name: 'test1'}}

et la clé cas n'est pas fournie en tant que paramètre de la méthode

i.e. [{name: 'test'}, {name: 'test1'}].ArrayToObject();

donnerait 

{0: {name: 'test'}, 1: {name: 'test1'}}
0
shubhamkes

Le moyen le plus simple de procéder est le suivant: 

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

function ConvertArr(arr) { 
 if (typeof(arr) === 'array') {
 Object.assign(obj, arr);
}

De cette façon, il ne s'exécutera que s'il s'agit d'un tableau. Cependant, vous pouvez l'exécuter avec let variable d'objet global ou sans, à vous de choisir. Si vous exécutez sans let, il suffit de faire Object.assign ({}, arr). 

0
Daniel Snell

Si vous aimez oneliners, et IE8 n'est plus un problème (comme il se doit)

['a','b','c'].reduce((m,e,i) => Object.assign(m, {[i]: e}), {});

Allez-y et essayez-le sur la console du navigateur

Cela pourrait être plus verbeux comme ceci:

['a','b','c'].reduce(function(memo,Elm,idx) {
    return Object.assign(memo, {[idx]: Elm});
}, {});

Mais exclut toujours IE8. Si IE8 est un must, vous pouvez utiliser le lodash/underscore comme ça:

_.reduce(['a','b','c'], function(memo,Elm,idx) {
    return Object.assign(memo, {[idx]: Elm});
}, {})
0
Carlos E. Alarcón