用lodash将对象转换为数组


165

我怎样才能改变一个大objectarray与lodash?

var obj = {
  22: {name:"John", id:22, friends:[5,31,55], works:{books:[], films:[],}
  12: {name:"Ivan", id:12, friends:[2,44,12], works:{books:[], films:[],}
}

// transform to 
var arr = [{name:"John", id:22...},{name:"Ivan", id:12...}]

@Mritunjay是的,因为文档对库的概述如此丰富……不。这只是一个详尽的功能列表,如果没有一个功能,遍历每个功能很可能会浪费时间。这个问题很公平。
Epirocks

Answers:


262

你可以做

var arr = _.values(obj);

有关文档,请参见此处。


34
如果您想将密钥保留为属性怎么办?(在这个例子中,如果id物业不存在,你想要一个基于对象的键来创建它。
迈克尔Liquori

8
您可以执行以下操作:var arr = _.values(_.mapKeys(obj, function(value, key) { value.id = key; return value; }));
Daniel Schmidt

1
@DanielSchmidt我不确定我做错了什么,但该示例仅为我返回了1行。:(因此,我所做的是手动推return值这样的数组:const divisionsList = []; _.mapKeys(divisions, (value, key) => { divisionsList[key] = value; });我会很感激任何意见或建议,以提高这种方法。
JohnnyQ

8
@JohnnyQ我想您需要使用mapValues代替,例如const toArrayWithKey = (obj, keyAs) => _.values(_.mapValues(obj, (value, key) => { value[keyAs] = key; return value; }));
orjan

1
@orjan是的,我实际上已经弄清楚了,只是忘了更新。谢谢你
JohnnyQ

38
_.toArray(obj);

输出为:

[
  {
    "name": "Ivan",
    "id": 12,
    "friends": [
      2,
      44,
      12
    ],
    "works": {
      "books": [],
      "films": []
    }
  },
  {
    "name": "John",
    "id": 22,
    "friends": [
      5,
      31,
      55
    ],
    "works": {
      "books": [],
      "films": []
    }
  }
]"

1
_.toArray()工作正常@jivings
Syed Zain Ali

4
仅获取值是一个不错的选择,但是toArray如果需要,则无法保留键。
Koushik Chatterjee

33

如果有人感兴趣的话,现代的本机解决方案:

const arr = Object.keys(obj).map(key => ({ key, value: obj[key] }));

或(不是IE):

const arr = Object.entries(obj).map(([key, value]) => ({ key, value }));

2
为什么不只是Object.keys(obj).map(key=>({key,value: obj[key]}))
Koushik Chatterjee

1
我喜欢它甚至没有用户lodash,干得好先生!
HungryPipo

1
@Dominic现在,您更改了完整的答案,并从我的评论中删除了它,即使没有提及(您已将其删除)。做得好
库希克·查特吉

1
@KoushikChatterjee重新添加了它
Dominic

2
这会更有用吗? const arr = Object.keys(obj).map(id => ({ id, ...obj[id] })); 这会将整个对象带入返回的数据中吗?(因为原始提问者想将其密钥存储为id道具,所以使用“ id”)
zabaat

20

对我来说,这可行:

_.map(_.toPairs(data), d => _.fromPairs([d]));

事实证明

{"a":"b", "c":"d", "e":"f"} 

进入

[{"a":"b"}, {"c":"d"}, {"e":"f"}]

1
我需要将对象转换为数组,以使原始对象的每个键/值都将是数组中的{key:value} -object。_.toPairs(data)接受对象{“ a”:“ b”,“ c”:“ d”,“ e”:“ f”}}并将其作为[[“” a“:” b“],[” c“:” d“],[” e“:” f“]]。_.fromPairs与此相反,它接受一个包含2个元素的数组:[“ a”,“ b”]并将其作为对象返回:{“ a”:“ b”}。使用_.map我遍历该数组,如果_.toPairs创建的数组借助_.fromPairs将其转换为对象数组。
NoNine17年

1
我很高兴我向下滚动看到了这一点。您的解决方案对我有用!谢谢!
Wale

@NoNine您不需要将map应用于(数组的)数组,可以将其直接应用于输入对象,并返回每个键值对,_.map(data, (v,k)=>({[k]: v}))请参见我的答案以获取详细信息。_.toPairs并且_fromPairs在这里是额外的和不必要的。
Koushik Chatterjee

这不是这个问题的目的。因为使用结果有点困难,因为每个条目都包含一个键(您不知道),并且您再次需要对每个单独的条目进行一些逻辑运算(例如Object.keys或Object.values)才能获得值每个玩具,如果玩具都想保留钥匙,则可以创建一系列结构类似的对象[{key: 'someKey', val: 'The value'}, {....},...]
Koushik Chatterjee

13

有很多方法可以得到您想要的结果。让我们按类别细分它们:

仅ES6值

主要方法是Object.values。但是使用Object.keysArray.map您也可以得到预期的结果:

Object.values(obj)
Object.keys(obj).map(k => obj[k])

ES6关键与价值

使用地图和ES6 动态/计算属性并进行销毁,您可以保留键并从地图返回对象。

Object.keys(obj).map(k => ({[k]: obj[k]}))
Object.entries(obj).map(([k,v]) => ({[k]:v}))

仅Lodash值

_.values但是,为此设计的方法有“快捷方式”之类_.map的实用程序方法_.toArray,它也将返回包含对象的数组。您也可以_.map使用_.keys并通过使用从对象获取值obj[key]符号。

注意:_.map传递对象时,将使用其baseMap处理程序,该处理程序基本上forEach是对象属性。

_.values(obj)
_.map(obj)
_.toArray(obj)
_.map(_.keys(obj), k => obj[k])

Lodash键和值

// Outputs an array with [[KEY, VALUE]]
_.entries(obj)
_.toPairs(obj)

// Outputs array with objects containing the keys and values
_.map(_.entries(obj), ([k,v]) => ({[k]:v}))
_.map(_.keys(obj), k => ({[k]: obj[k]}))
_.transform(obj, (r,c,k) => r.push({[k]:c}), [])
_.reduce(obj, (r,c,k) => (r.push({[k]:c}), r), [])

请注意,在以上示例中使用了ES6(箭头功能和动态属性)。_.fromPairs如果存在ES6问题,则可以使用lodash 和其他方法来组成对象。


12

如果希望将键(在这种情况下为id)保留为每个数组项的属性,则可以执行

const arr = _(obj) //wrap object so that you can chain lodash methods
            .mapValues((value, id)=>_.merge({}, value, {id})) //attach id to object
            .values() //get the values of the result
            .value() //unwrap array of objects

8

2017年更新:Object.values,lodash toArray做到了。并保留键映射散布运算符可以很好地发挥作用:

// import { toArray, map } from 'lodash'
const map = _.map

const input = {
  key: {
    value: 'value'
  }
}

const output = map(input, (value, key) => ({
  key,
  ...value
}))

console.log(output)
// >> [{key: 'key', value: 'value'}])
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>


7

使用普通JavaScriptECMAScript-2016)将对象转换为数组Object.values

var obj = {
    22: {name:"John", id:22, friends:[5,31,55], works:{books:[], films:[]}},
    12: {name:"Ivan", id:12, friends:[2,44,12], works:{books:[], films:[]}}
}

var values = Object.values(obj)

console.log(values);

如果您还想保留键的使用方式Object.entriesArray#map例如:

var obj = {
    22: {name:"John", id:22, friends:[5,31,55], works:{books:[], films:[]}},
    12: {name:"Ivan", id:12, friends:[2,44,12], works:{books:[], films:[]}}
}

var values = Object.entries(obj).map(([k, v]) => ({[k]: v}))

console.log(values);


5

var arr = _.map(obj)

您可以使用_.map功能(两者lodashunderscore用)object,以及,它会在内部处理这种情况下,迭代每个值和关键你iteratee,最后返回数组。实际上,您可以使用它而无需任何迭代(仅_.map(obj)如果只需要一个值数组,则)。好处是,如果您需要在两者之间进行任何转换,则可以一次性完成。

例:

但是,如果您要转换对象,则可以这样做,即使您需要保留键,也可以在_.map(obj, (v, k) => {...}其中添加其他参数来执行(),map然后按需要使用它。

但是,还有其他Vanilla JS解决方案(因为每个lodash解决方案都应该是纯JS版本),例如:

  • Object.keys然后将map它们转化为价值
  • Object.values (在ES-2017中)
  • Object.entries然后是map每个键/值对(在ES-2017中)
  • for...in 循环并使用每个键填充值

还有更多。但是,由于这个问题是针对lodash(并假设有人已经使用过)的,因此您无需考虑太多有关版本,方法支持和错误处理(如果找不到)的问题。

还有其他lodash解决方案,例如_.values(对于特定的目的更具可读性),或者先进行配对再映射,等等。但是,如果您的代码需要灵活性,可以在将来需要保留keys或转换值时进行更新,那么最好的解决方案是_.map在此答案中使用单个。按照可读性,这将不那么困难。


2
尼斯,非常简单,最简洁。
edencorbin

5

对象到数组

在所有答案中,我认为这是最好的:

let arr = Object.entries(obj).map(([key, val]) => ({ key, ...val }))

会改变:

{
  a: { p: 1, q: 2},
  b: { p: 3, q: 4}
}

至:

[
  { key: 'a', p: 1, q: 2 }, 
  { key: 'b', p: 3, q: 4 }
]

数组到对象

要变回:

let obj = arr.reduce((obj, { key, ...val }) => { obj[key] = { ...val }; return obj; }, {})

要转换回保留键值:

let obj = arr.reduce((obj, { key, ...val }) => { obj[key] = { key, ...val }; return obj; }, {})

会给:

{
  a: { key: 'a', p: 1, q: 2 },
  b: { key: 'b', p: 3, q: 4 }
}

对于最后一个示例,您还可以使用lodash _.keyBy(arr, 'key')_.keyBy(arr, i => i.key)


3

如果要将对象的某些自定义映射关系(例如原始Array.prototype.map)映射到Array中,则可以使用_.forEach

let myObject = {
  key1: "value1",
  key2: "value2",
  // ...
};

let myNewArray = [];

_.forEach(myObject, (value, key) => {
  myNewArray.push({
    someNewKey: key,
    someNewValue: value.toUpperCase() // just an example of new value based on original value
  });
});

// myNewArray => [{ someNewKey: key1, someNewValue: 'VALUE1' }, ... ];

参见lodash_.forEach的文档https://lodash.com/docs/#forEach

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.