将数组转换为对象

什么是最好的转换方式:

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

至:

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

有了这样的function:

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

你的数组已经或多或less只是一个对象,但是数组对于整型命名的属性确实有一些“有趣的”和特殊的行为。 以上将给你一个普通的对象。

编辑哦,你也可能要考虑arrays中的“洞”:

 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()工作原理。

你可以使用累加器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}

您的累加器可以是任何types,为您的具体目的。 例如,为了交换数组中的对象的键和值,传递[]

 [{ 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"}]

map不同, reduce可能不能用作1-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"}]

注意reduceObject.keyECMA 5th edition一部分; 你应该为不支持它们的浏览器提供一个polyfill(特别是IE8)。

查看Mozilla的默认实现。

ECMAScript 6引入了易于聚合的Object.assign

Object.assign()方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。 它会返回目标对象。

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

数组的自身length属性不会被复制,因为它不是可枚举的。

如果你使用jQuery:

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

我可能会这样写(因为很less我不会有underscorejs库在手边):

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

为了完整性,ECMAScript 2015(ES6)正在推广。 将需要一个翻译(巴比伦)或至lessES6的环境。

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

这是一个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 

惊讶不见 –

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

在现代JavaScript中简单的方法是使用Object.assign() ,它只是将key:value从一个对象复制到另一个对象。 在我们的例子中, Array将属性捐献给新的{}

五年后,有一个好方法:)

Object.assign在ECMAScript 2015中引入。

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

快速和肮脏#2:

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

一个快速和肮脏的:

 var obj = {}, arr = ['a','b','c'], l = arr.length; while( l && (obj[--l] = arr.pop() ) ){}; 

我只要用Array.of()就可以做到这一点。 数组有能力使用它的上下文作为构造函数。

注2:函数是有意通用的工厂方法; 它不要求它的这个值是数组的构造函数。 因此它可以被转移到其他可以用一个数字参数调用的构造函数或由其inheritance。

所以我们可以将Array.of()绑定到一个函数,并像对象一样生成一个数组。

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

从Lodash 3.0.0开始,你可以使用_.toPlainObject

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

这是一个咖啡的解决scheme

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

这允许您从数组中生成一个对象,其中包含您按照所需顺序定义的键。

 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); 会输出“paint”,函数必须有等长的数组或者你得到一个空的对象。

这是一个更新的方法

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

这是我刚写的一个recursion函数。 这很简单,运作良好。

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

结果: 递归数组到对象

如果你使用的是angularjs,你可以使用angular.extend,和jquery的$ .extend一样。

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

如果你可以使用Map或者Object.assign ,那很简单。

创build一个数组:

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

下面创build一个索引作为键的对象:

 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 

你可以使用这样的function:

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

这个应该更有效地处理稀疏数组。

 .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 ] } 

[/文档]

这不是直接相关,但我来这里寻找合并嵌套对象,如一个class轮

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

解决scheme是使用reduce和object spread的组合:

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

我最终使用了对象扩展运算符,因为它是ECMAScript 2015(ES6)标准的一部分。

 const array = ['a', 'b', 'c']; console.log({...array}); 

以下面的小提琴为例。

我们可以使用Object.assignarray.reduce函数将一个数组转换为对象。

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

我多次面对这个问题,并决定编写一个尽可能通用的函数。 有一个外观和随意修改任何东西

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

我会使用下划线为这,但如果不可用,那么我会下降到初始值为空的对象使用减less{}

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

减less应该在今天的大多数浏览器中广泛使用,参见MDN

使用JavaScript,你可以做到这一点forEach

 var result = {}, attributes = ['a', 'b','c']; attributes.forEach(function(prop,index) { result[index] = prop; }); 

如果你喜欢的话,IE8不再是一个问题了(因为它应该是)

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

继续并在浏览器控制台上尝试

它可以是这样更详细的:

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

但仍然排除IE8。 如果IE8是必须的,那么你可以使用lodash /下划线:

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

这是很容易使用JavaScript减less:

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

你可以看看Array.prototype.reduce(), https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

初始数组,并将转换成一个对象与键将是一个数组的唯一元素和键的值将多less次的关键将重复

 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)