【问题标题】:Get only some keys of object of objects仅获取对象对象的一些键
【发布时间】:2021-02-03 01:57:25
【问题描述】:

我有这个对象:

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,
    "c": 3,
  },
  "2020": {
    "a": 2,
    "c": 6,
  },
  "2021": {
    "a": 10,
    "c": 12,
  }
}

const obj2 = {
  "2019": {
    "b": 2,
    "d": 4
  },
  "2020": {
    "b": 4,
    "d": 8
  },
  "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 } }
]

差不多了,但并不完美。哪种方法更好?

【问题讨论】:

  • 分离a,cb,d背后的逻辑是什么
  • 没有逻辑,我需要这样拆分对象
  • 所以它总是一个具有abcd 属性的对象?而且您总是希望ac 在一个对象中,而bd 在另一个对象中?
  • 最终你想要一个对象,所以当你从Object.entries开始时,你会以某种方式回到Object.fromEntriesArray.reduce

标签: javascript data-structures mapping reduce


【解决方案1】:

您可以结合使用mapreduce 方法和一个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)

【讨论】:

    【解决方案2】:

    问题是map 返回一个包含替换元素的数组,而您需要一个对象。

    由于您已经在使用 Lodash,您可以使用 mapValues 来转换对象的值并返回对象而不是数组。

    function pickKeys(dataObj, keys) {
      return _.mapValues(dataObj, obj => _.pick(obj, keys));
    }
    

    function pickKeys(dataObj, keys) {
      return _.mapValues(dataObj, obj => _.pick(obj, 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>

    【讨论】:

      【解决方案3】:

      您可以使用给定对象的条目映射想要的键。

      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', 'c'], ['b', '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; }

      【讨论】:

        【解决方案4】:

        下一个提供的示例代码是基于 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,
            "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 [
        
          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; }

        【讨论】:

          猜你喜欢
          • 2019-07-25
          • 2018-09-02
          • 2022-01-24
          • 2020-02-07
          • 1970-01-01
          • 2012-09-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多