根据键数组更改数据集对象的形状

时间:2020-10-19 09:25:23

标签: javascript arrays object

假设我有

const KEYS = ['b', 'a', 'c']
const obj = {
  2018: {a: 1, b: 2, c: 3},
  2019: {a: 4, b: 5, c: 6},
  2020: {a: 7, b: 8, c: 9},
}

这就是我想要得到的:

const result = {
 2018: { 
    a: [0, 1, 0], 
    b: [2, 0, 0], 
    c: [0, 0, 3] 
  },
 2019: { 
    a: [0, 4, 0], 
    b: [5, 0, 0], 
    c: [0, 0, 6] 
  },,
 2020: { 
    a: [0, 7, 0], 
    b: [8, 0, 0], 
    c: [0, 0, 9] 
  },
}

result ['2018']对象具有三个键。每个键值都是一个数组,其中包含按KEYS使用0作为填充值设置的顺序的值。

我该怎么做? 这是我尝试过的,但显然比这复杂:

const reshaped = Object.entries(obj).map(([key, value]) => {
  return { [key]: Object.values(value) }
})

// [
//  { 2018: [ 1, 2, 3 ] },
//  { 2019: [ 4, 5, 6 ] },
//  { 2020: [ 7, 8, 9 ] }
// ]

2 个答案:

答案 0 :(得分:1)

您可以结合使用Object.entriesObject.fromEntries来映射对象,然后仅创建一个具有KEYS arr长度的新数组。

const KEYS = ['b', 'a', 'c']
const obj = {
  2018: {a: 1, b: 2, c: 3},
  2019: {a: 4, b: 5, c: 6},
  2020: {a: 7, b: 8, c: 9},
}

const result = Object.fromEntries( // Create obj from array of entries
  Object.entries(obj).map(([key, value]) => [ // create array of entries from obj and map it
    key,
    Object.fromEntries( // do the same obj/arr transformation on the value
      Object.entries(value).map(([subKey, subValue]) => {
        const arr = new Array(KEYS.length).fill(0); // create new array of keys length and fill all zeroes
        arr[KEYS.indexOf(subKey)] = subValue; // on the index of the key in the KEYS arr, set the value of the key

        return [subKey, arr]; // return subValue
      })
    )
  ])
);

console.log(result);

答案 1 :(得分:1)

您可以映射所需的键,以便为每个属性构建一个数组。

const
    KEYS = ['b', 'a', 'c'],
    object = { 2018: { a: 1, b: 2, c: 3 }, 2019: { a: 4, b: 5, c: 6 }, 2020: { a: 7, b: 8, c: 9 } },
    result = Object.fromEntries(Object.entries(object).map(([k, o]) => [
        k,
        Object.fromEntries(Object.entries(o).map(([l, v]) => [
            l,
            KEYS.map(m => l === m ? v : 0)
        ]))
    ]));
    
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }