将数组转换为对象

转换的最佳方法是什么:

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

到:

{
0: 'a',
1: 'b',
2: 'c'
}
1510442 次浏览

使用这样的函数:

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()的工作方式。

一个快速而肮脏的:

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


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

你可以使用这样的函数:

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

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

如果您使用的是jQuery:

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

我已经多次面对这个问题,并决定编写一个尽可能通用的函数。看看并随时修改任何东西

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

我可能会这样写(因为我很少手边没有underScorejs库):

var _ = require('underscore');


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

更OO的方法:

Array.prototype.toObject = function() {
var Obj={};


for(var i in this) {
if(typeof this[i] != "function") {
//Logic here
Obj[i]=this[i];
}
}


return Obj;
}

快速和肮脏#2:

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


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

这是咖啡因的解决方案

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

一种简单而厚颜无耻的方法,可以快速将项目数组转换为对象

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

使用like:

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

您可以使用累加器,即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"}]

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的一部分;您应该为不支持它们的浏览器(特别是IE8)提供一个Poly填充。

请参阅Mozilla的默认实现。

我的版本数组到JS中的json。Jusy复制/粘贴并使用它。这不是很棒吗?我喜欢我在StackOverflow上找到的这种类型的函数。

function array2json(arr) {
var parts = [];
var is_list = (Object.prototype.toString.apply(arr) === '[object Array]');


for(var key in arr) {
var value = arr[key];
if(typeof value == "object") { //Custom handling for arrays
if(is_list) parts.push(array2json(value)); /* :RECURSION: */
else parts[key] = array2json(value); /* :RECURSION: */
} else {
var str = "";
if(!is_list) str = '"' + key + '":';


//Custom handling for multiple data types
if(typeof value == "number") str += value; //Numbers
else if(value === false) str += 'false'; //The booleans
else if(value === true) str += 'true';
else str += '"' + value + '"'; //All other things
// :TODO: Is there any more datatype we should be in the lookout for? (Functions?)


parts.push(str);
}
}
var json = parts.join(",");


if(is_list) return '[' + json + ']';//Return numerical JSON
return '{' + json + '}';//Return associative JSON
}

这是我刚刚写的一个递归函数。它很简单,效果很好。

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

结果: 递归数组到对象

我会为此使用下划线,但如果它不可用,那么我会下拉到使用Reduce,初始值为空对象{}

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

Reduce应该在今天的大多数浏览器中广泛可用,请参阅MDN

如果你使用的是angularjs,你可以使用angular.extend,与jQuery的$。

var newObj = {};
angular.extend(newObj, ['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

使用javascript#forEach可以做到这一点

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


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

使用ECMA6:

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

为了完整性,ECMAScript 2015(ES6)扩展。将需要一个转译器(Babel)或至少运行ES6的环境。

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

ECMAScript 6引入了易于多填充的Object.assign

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

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

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

此外,您可以在对象上使用ES8扩展语法来实现相同的结果:

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

对于自定义密钥,您可以使用减少

['a', 'b', 'c'].reduce((a, v) => ({ ...a, [v]: v}), {})
// { a: "a", b: "b", c: "c" }
.reduce((o,v,i)=>(o[i]=v,o), {})

[docs]

或更冗长

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]内部文档

如果你喜欢单线程序,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是必须的,那么你可以像这样使用洛塔什/下划线:

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

使用JavaScript Reduce很容易:

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

我会简单地用Array.of()来做这件事。Array of能够使用它的上下文作为构造函数。

注释2 of函数是一个有意通用的工厂方法;它 不要求其this值是Array构造函数。 因此,它可以转移到或由其他构造函数继承 可以用单个数字参数调用。

因此,我们可以将Array.of()绑定到一个函数并生成一个类似数组的对象。

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

通过使用Array.of()甚至可以做数组子类化

从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>

初始数组,并将转换为带有键的对象,键将是数组的唯一元素,键值将是特定键重复的次数

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)

如果您使用ES6,则可以使用Object.assign和扩展运算符

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

如果你有嵌套数组,比如

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

如果您可以使用MapObject.assign,则非常容易。

创建一个数组:

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

下面创建一个以index为键的对象:

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

这不是直接相关的,但我来这里寻找一个用于合并嵌套对象的单行程序,例如

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

解决方案是结合使用Reduce和Object Extra:

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

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

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


console.log(newObj)

下面的方法将数组转换为具有特定给定键的对象。

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

对于前-

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

会给

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

并且不提供incase键作为方法的参数

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

会给

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

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

最简单的方法是这样做:

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


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

这样它只在它是一个数组时运行,但是,你可以使用let全局对象变量或不使用let运行它,这取决于你,如果你没有let运行,只需做Object.assign({}, arr)。

FWIW,另一个最近的方法是使用新的Object.fromEntriesObject.entries如下:

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

…这允许避免将稀疏数组项存储为undefinednull并保留非索引(例如,非正整数/非数字)键。

{0:"a",1:"b",2:"c","-2":"d", hello:"e"}

(这里的结果与@Paul Draper的Object.assign答案相同。

但是,人们可能希望添加arr.length,因为它不包括:

obj.length = arr.length;

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

使用javascript Lodash库。有一个简单的方法 _.mapKeys(object, [iteratee=_.identity]) 可以进行转换。

支持更多浏览器更灵活这样做的方式是使用正常的循环,类似于:

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


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

但现代的方式也可以使用点差算子,例如:

{...arr}

或者对象分配

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

两者都将返回

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

尝试使用反射从数组项复制到对象。

var arr =['aa:23','bb:44','cc:55']
var obj ={}
arr.forEach(e => {
var ee = e.split(':')
Reflect.set(obj,ee[0],ee[1])
});
console.log(obj) // { aa: '23', bb: '44', cc: '55' }

var finalResult = ['a','b','c'].map((item , index) => ({[index] : item}));
console.log(finalResult)

如果您想使用迭代对象的一个属性作为键,例如:

// from:
const arr = [
{
sid: 123,
name: 'aaa'
},
{
sid: 456,
name: 'bbb'
},
{
sid: 789,
name: 'ccc'
}
];
// to:
{
'123': { sid: 123, name: 'aaa' },
'456': { sid: 456, name: 'bbb' },
'789': { sid: 789, name: 'ccc' }
}

用途:

const result = arr.reduce((obj, cur) => ({...obj, [cur.sid]: cur}), {})

如果有人在搜索TypeScript方法,我写了这个:

const arrayToObject = <T extends Record<K, any>, K extends keyof any>(
array: T[] = [],
getKey: (item: T) => K,
) =>
array.reduce((obj, cur) => {
const key = getKey(cur)
return ({...obj, [key]: cur})
}, {} as Record<K, T>)

它将:

  1. 强制第一个参数是对象数组
  2. 帮助选择密钥
  3. 强制密钥成为所有数组项的键

示例:

// from:
const array = [
{ sid: 123, name: 'aaa', extra: 1 },
{ sid: 456, name: 'bbb' },
{ sid: 789, name: 'ccc' }
];
// to:
{
'123': { sid: 123, name: 'aaa' },
'456': { sid: 456, name: 'bbb' },
'789': { sid: 789, name: 'ccc' }
}

用法:

const obj = arrayToObject(array, item => item.sid) // ok
const obj = arrayToObject(array, item => item.extra) // error

这是一个演示

打字稿解决方案:

export const toMap = (errors: ResponseError[]) => {
const errorMap: Record<string, string> = {};
errors.forEach(({ field, message }) => {
errorMap[field] = message;
});
return errorMap;
};


export type FieldError = {
field: string;
message: string;
};
import books from "./books.json";


export const getAllBooks = () => {
return {
data: books,
// a=accoumulator, b=book (data itelf), i=index
bookMap: books.reduce((a, book, i) => {
// since we passed {} as initial data, initially a={}
// {bookID1:book1, bookID2:i}
a[book.id] = book;
// you can add new property index
a[book.id].index=i
return a;
// we are passing initial data structure
}, {}),
};
};

这里没有多少人评论#E YZ 0,我真的很喜欢它,因为它更干净,并且可以轻松地与TypeScript一起工作,而不会过多关注泛型类型和东西。如果需要,它还允许使用地图自定义密钥。缺点:如果你想要一个自定义密钥,你需要一个额外的map。例如:

const tags = [
{ name: 'AgeGroup', value: ageGroup },
{ name: 'ApparelTypes', value: apparelTypes },
{ name: 'Brand', value: brand },
// ...
]


const objectTags = Object.fromEntries(tags.map((t) => [t.name, t.value]))


/*
{
AgeGroup: 'Adult',
Apparel: 'Creeper, Jacket'
Brand: '',
// ...
}
*/

为什么没有人尝试这个?在ES6中

let arr = ['a','b','c']
let {...obj} = arr
console.log(obj) //  {0: 'a', 1: 'b', 2: 'c'}
let {...obj2} = ['a','b','c']
console.log(obj2) //  {0: 'a', 1: 'b', 2: 'c'}

很简单的方法?

如果您的数组包含2元素数组,其中第一个元素是键,第二个元素是值,您可以使用reduce轻松转换为对象。

[
["key1","value1"],
["key2", "value2"],
["key3", "value3"]
]
.reduce((acc, [key, value])=>({...acc, [key]: value}), {});

结果:

{
key1: 'value1',
key2: 'value2',
key3: 'value3'
}

最简短的答案:(使用解构)

const obj = { ...input }

示例:

const inputArray = ["a", "b", "c"]
const outputObj = { ...inputArray }