问题描述
我有这个对象:
const dataset = {
"2019": {
"a": 1,"b": 2,"c": 3,"d": 4
},"2020": {
"a": 2,"b": 4,"c": 6,"d": 8
},"2021": {
"a": 10,"b": 11,"c": 12,"d": 13
}
}
我想获得这两个对象:
const obj1 = {
"2019": {
"a": 1,},}
}
const obj2 = {
"2019": {
"b": 2,"2020": {
"b": 4,"2021": {
"b": 11,"d": 13
}
}
因此,根据内部对象的某些键将对象“拆分”为两个对象。 这是我尝试过的:
function pickKeys(dataObj,keys) {
return Object.entries(dataObj).map(([d,obj]) => {
return { [d]: _.pick(obj,keys) }
})
}
const obj1 = pickKeys(dataset,['a','c'])
结果是:
const obj1 = [
{ '2019': { a: 1,c: 3 } },{ '2020': { a: 2,c: 6 } },{ '2021': { a: 10,c: 12 } }
]
所以几乎在那里,但这并不完美。哪种方法更好?
解决方法
您可以使用map
,reduce
方法和一个for...in
循环的组合来执行此操作,该循环会将键数组转换为对象数组。然后,您可以使用数组解构来获取两个单独的对象。
const dataset = {"2019":{"a":1,"b":2,"c":3,"d":4},"2020":{"a":2,"b":4,"c":6,"d":8},"2021":{"a":10,"b":11,"c":12,"d":13}}
const [a,b] = [['a','c'],['b','d']]
.map(keys => keys.reduce((r,key) => {
for (let year in dataset) {
if (!r[year]) r[year] = {}
r[year][key] = dataset[year][key]
}
return r;
},{}))
console.log(a)
console.log(b)
,
问题是map
返回一个带有替换元素的数组,而您需要一个对象。
由于您已经在使用Lodash,因此可以使用mapValues
来转换对象的值并返回对象而不是数组。
function pickKeys(dataObj,keys) {
return _.mapValues(dataObj,obj => _.pick(obj,keys));
}
function pickKeys(dataObj,keys));
}
const dataset = {
"2019": {
"a": 1,"b": 2,"c": 3,"d": 4
},"2020": {
"a": 2,"b": 4,"c": 6,"d": 8
},"2021": {
"a": 10,"b": 11,"c": 12,"d": 13
}
}
console.log(pickKeys(dataset,["a","c"]));
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.15/lodash.min.js"></script>
,
您可以使用给定对象的条目来映射所需的键。
const
dataset = { 2019: { a: 1,b: 2,c: 3,d: 4 },2020: { a: 2,b: 4,c: 6,d: 8 },2021: { a: 10,b: 11,c: 12,d: 13 } },groups = [['a','d']],[result1,result2] = Object
.entries(dataset)
.reduce((r,[k,o]) =>
groups.map((group,i) =>
group.reduce(
(q,g) => ({ ...q,[k]: { ...q[k],[g]: o[g] } }),r[i] || {}
)
),[]
);
console.log(result1);
console.log(result2);
.as-console-wrapper { max-height: 100% !important; top: 0; }
,
下一个提供的示例代码基于reduce
,是通用的,但其用法可以配置...
function createAndCollectSubdata(collector,dataEntry) {
const { keyLists,subdataList } = collector;
const [ dataKey,dataValue ] = dataEntry;
keyLists.forEach((keyList,idx) => {
const data = subdataList[idx] || (subdataList[idx] = {});
const subdata = data[dataKey] || (data[dataKey] = {}) ;
keyList.forEach(key => subdata[key] = dataValue[key]);
});
return collector;
}
const dataset = {
"2019": {
"a": 1,"d": 13
}
};
const [
acSubdata,bdSubdata
] = Object.entries(dataset).reduce(createAndCollectSubdata,{
keyLists: [["a","c"],["b","d"]],subdataList: []
}).subdataList;
console.log('acSubdata :',acSubdata);
console.log('bdSubdata :',bdSubdata);
.as-console-wrapper { min-height: 100%!important; top: 0; }