ChatGPT解决这个技术问题 Extra ChatGPT

将数组转换为对象

转换的最佳方法是什么:

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

至:

{
  0: 'a',
  1: 'b',
  2: 'c'
}
值得指出的是,Javascript 数组是对象。
如果其他人正在寻找 Lodash 解决方案,请考虑 _.keyBy(以前称为 _.indexBy):lodash.com/docs#keyBy
这有点令人困惑,因为数组已经是对象,但我猜问题的重点是将 array exotic object 转换为 ordinary object
使用 Lodash 执行此操作的一种简单方法是 _.toPlainObject。例如:var myObj = _.toPlainObject(myArr)

D
David Hellsing

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

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

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

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

此外,您可以在对象上使用 ES8 spread syntax 来实现相同的结果:

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

对于自定义键,您可以使用 reduce

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

只是想指出 - 如果您已经拥有来自原始对象的排序属性数组,则使用 spread 运算符可以将该数组直接转换为新对象:{ ...[sortedArray]}
Oriol,有没有办法设置固定键而不是 0 和 1?
这通常不是你想要的。通常您希望使用数组元素中的属性作为键。因此,reduce 就是你想要的。
如果我希望密钥不是 0,1,2 而与值相同怎么办?比如:{a: 'a'} 我们怎么做?
@Gel 使用 reduce 喜欢:arr.reduce((a, v) => ({ ...a, [v]: v}), {})
J
Jordan Frankfurt

使用这样的功能:

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


@m93a 它已经是一个对象。在 JavaScript 中,如果您不打算使用数字属性键和“长度”属性,那么创建 Array 实例 ([]) 确实没有意义。
避免参数重新分配 const obj = arr.reduce((obj, cur, i) => { return { ...obj, [i]: cur }; }, {}); 的更简洁方法
没有显式返回的箭头 + 解构语法:const obj = arr.reduce((obj, cur, i) => ({ ...obj, [i]: cur }), {});
正如@VivekN 所说,每次都需要创建新对象吗? arr.reduce((obj, cur, i) => (obj[i]=cur,obj), {}); 呢?
@eugene_sunic 确实,但是当我在 2010 年回答这个问题时,这种方法不可用:)
r
roland

您可以使用累加器,即 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)提供一个 polyfill。

查看 Mozilla 的默认实现。


当您使用对象映射并且需要删除其中一个键时,有助于维护 redux 存储
M
Max

如果您使用的是 jquery:

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

奇怪的是,如果我给出一个数组变量,它会将每个字符放在一个单独的对象中:0:“a”,1:“,”,2:“b”......所以它忽略引号,但包括逗号...... .
@Max我认为没有这种行为。返回的对象是 {0: 'a', 1: 'b', 2: 'c'},这是预期的结果。
有没有办法在使用 $.extend 的同时以非数字方式通知键,即:对数组项进行计算?
超级可怕和简短的测试
v
vsync

为了完整起见,ECMAScript 2015(ES6) 传播。将需要转译器(Babel)或至少运行 ES6 的环境。

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


实际上这在 ES2015 中也不是原生可用的。然而,它非常优雅。
如何使用传播获得结果 - { "a": "a", "b":"b", "c":"c" }?
P
Prerna Jain

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

var _ = require('underscore');

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

你对我的回复投了反对票,但没有评论?我的答案是正确的并且经过测试。反对意见是什么?
这个问题没有下划线标记,并且您还假设 node.js 或 require 库。
下划线在客户端和服务器上都很常见。它被假定为 Backbone.js,并且可能是最常见的实用程序库。话虽如此,我包含了 require 行以明确我正在使用库。没有 1-liner 用于描述“将 underscore.js 添加到您的页面”,因此浏览器环境需要一些翻译
不过,如果您使用的是 unssercore,一个简单的 obj=_.extend({},a); 就可以完成这项工作。此外,如果您要遍历数组,我会说 _.each_.map 更合适。总而言之,这在几个层面上都不是一个好的答案。
@CharlieMartin 这种类比是完全有缺陷的,因为 lodash、underscore 和 jQuery 不是“标准库”,并且在大量 JavaScript 用例中,添加库会直接影响最终用户,出于微不足道的原因不应该这样做。
J
Johnathan Kanarek

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

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

我想知道这个减少的东西有多快。在每次迭代中,对象都会使用扩展运算符一次又一次地克隆?
K
KARTHIKEYAN.A

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

var arr = [{a:{b:1}},{c:{d:2}}] var newObj = arr.reduce((a, b) => Object.assign(a, b), {})控制台日志(新对象)


这就是我一直在寻找的。我不需要索引,我需要将数组转换为保留的键值对。
加上一个功夫,我需要它来将 arr = [{ b: 1, d: 2 }] 转换为 obj。
B
Benjamin Gruenbaum

这是一个 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) Therefore, I think Object.assign is much better
@Oriol mdn 是错误的,至少在 V8(以及其他引擎)中,在这种特殊情况下这是一个非常快的操作 - 因为无论如何对象都有一个数字存储,这基本上是在更改两个指针。
这也可以用于这样一个事实,即它在其他快速解决方案中显然是唯一的,即保留数组上的任何非索引(“自己的”)属性(即,非正整数属性)......
但是嗯,Array.isArray 在这里为“对象”返回 true,即使 instanceof Array 没有...
@BrettZamir 听起来像一个错误:D
B
Brett Zamir

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”,你好:“e”}

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

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

obj.length = arr.length;

您可以使用 arr.entries() 而不是 Object.entries(arr)
R
RIYAJ KHAN

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

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

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

使用 ECMA6:

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

m
murthy naika k

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

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

如果您有嵌套数组,例如

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

不仅您的变量名称不同,而且您的示例将不起作用,从构造函数创建映射最初需要 2d 键值数组。 new Map([['key1', 'value1'], ['key2', 'value2']]);
M
Mic

一个快速而肮脏的:

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 开头并递减。
是的..只是改变了它,但后来它变得不那么有趣了:/
甚至可以先做l = arr.length,然后再做while (l && (obj[--l] = arr.pop())){}(我知道这很旧,但为什么不进一步简化它)。
@Qix,不错的缩短
它比其他解决方案更快吗?
l
lordkrandel

又快又脏#2:

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

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

你为什么使用逗号符号?
个人偏好在下一行使用逗号。我发现这个符号更容易阅读。
如果数组包含虚假值,则循环将停止。您应该检查 i < a.length 而不是 a[i]
A
Alireza

更多的浏览器支持和更灵活的方式是使用普通循环,例如:

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

M
Mark Giblin

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

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); 将输出“paint”,该函数必须具有相等长度的数组,否则您将得到一个空对象。

这是一个更新的方法

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 通过引用对象/数组的属性自动执行操作。
不,它没有,例程复制,原件不受影响。
是的,原版被触动了。请参阅jsfiddle.net/bRTv7。数组长度最终都为 0。
好的,我刚刚更改的编辑版本不会破坏数组,发现它应该这样做很奇怪。
更新的方法应该在旧浏览器中得到支持,因为 JSON 的存在时间比 ECMA 添加的新代码特性要长
t
test30
.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] 有何打算?使代码片段可执行会更有用。
a
acontell

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

var obj = _.toPlainObject(['a', 'b', 'c']);控制台.log(obj);


S
Shannon Hochkins

如果可以使用 MapObject.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

i
isherwood

如果有人在寻找 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>)

它会:

强制第一个参数是对象数组帮助选择键强制键是所有数组项的键

例子:

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

Here's a demo


这很好,很容易修改以满足其他要求
优秀的小解决方案,就像一个魅力!如何根据您的示例将输出更改为 '123': 'aaa'?
任何想要做我需要的人的修改函数: 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]: Object.entries(cur).reduce((str, [p, val]) => { return ${val}; }, '') }) }, {} as Record);
J
JVE999

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

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

https://i.stack.imgur.com/KZHoT.png


效果很好。谢谢
这应该更高,如果您有 ['a' = '1', 'b' = '2', 'c' = '3'] 并希望它像 {a: 1, b: 2, c: 3} 一样完美。
C
Community

我只需使用 Array.of() 即可。 Array of has the ability to use it's context as a constructor.

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

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

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

通过利用 Array.of() one can even do array sub-classing


M
Mahdi Bashirpour

让我 = 0;让 myArray = [“第一”,“第二”,“第三”,“第四”]; const arrayToObject = (arr) => Object.assign({}, ...arr.map(item => ({[i++]: item}))); console.log(arrayToObject(myArray));

或使用

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


S
SridharKritha

ES5 - 解决方案:

使用数组原型函数“push”和“apply”,您可以使用数组元素填充对象。

var arr = ['a','b','c']; var obj = 新对象(); Array.prototype.push.apply(obj, arr);控制台.log(obj); // { '0': 'a', '1': 'b', '2': 'c', length: 3 } console.log(obj[2]); // C


如果我想转换为 { name: a, div :b, salary:c} 怎么办
B
Bhangun Hartani

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

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

P
Pablo Cabrera

你可以使用这样的函数:

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

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


A
Adnan Y

它不是直接相关的,但我来这里是为了寻找一个用于合并嵌套对象的衬垫,例如

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

解决方案是结合使用 reduce 和 object spread:

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

另外,Object.fromEntries(Object.entries(nodes).map(([key, value] => [key, value.interfaces]))
D
Daniel Snell

最简单的方法如下:

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

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

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


这与 top answer 中提供的解决方案相同
a
ascripter

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


D
David

这是咖啡脚本中的解决方案

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

什么是咖啡脚本?我们在谈论JS! :D
这是一种编译成 JavaScript 的小语言 :)
哼,它使用了奇怪的符号。我更喜欢纯JS。
@David您可以在 1 行上执行整个 for 循环,以使整个事情只有 3 行。 :) 示例:obj[i] = v for v,i in arr when v?