这是进一步扩展previous question.的尝试。我觉得这完全不同,可以提出另一个主题,希望能帮助尝试解决同一问题的任何人。

如果我有一个键-值对的数据集,那么我要完成三件事:


查找内部键值对的值的第一个匹配项。
将该值复制到地图中
将另一个键值对的值用作Map的键。


因此,举例来说,我有以下数据集:

[
  {"date":"2019-01-01", "temp":"cold", "season":"winter", "precip":"snow"},
  {"date":"2019-02-01", "temp":"cold", "season":"winter", "precip":"none"},
  {"date":"2019-03-01", "temp":"mild", "season":"spring", "precip":"rain"},
  {"date":"2019-04-01", "temp":"mild", "season":"spring", "precip":"none"},
  {"date":"2019-05-01", "temp":"warm", "season":"spring", "precip":"rain"},
  {"date":"2019-06-01", "temp":"warm", "season":"summer", "precip":"hail"},
  {"date":"2019-07-01", "temp":"hot", "season":"summer", "precip":"none"}
]


我想结束以下Map对象:

[
  "2019-01-01" => "snow",
  "2019-02-01" => "none",
  "2019-03-01" => "rain",
  "2019-06-01" => "hail"
]


作为最后的挑战,如何在可以动态生成结果的函数中执行此操作?因此,在上面的示例中,我在最终Map中选择了“ precip”作为所需值。但是,如果我想要“季节”怎么办?有没有一种方法可以动态地做到这一点,在这里我可以将“键”名作为函数的参数传递?

另外,此操作是否有名称?我很难拿到头衔。如果有人有更好的主意,我很乐意将其重命名。我觉得这是很多人都可能遇到的一个优雅的问题。

最佳答案

您可以使用


Array#filter删除所有最终会产生重复值的条目
Array#map在您的数据上生成键值对
只是collect into a Map via the constructor


要使其具有动态性,您只需要提供用于键和值的属性名称即可:



const data = [
  {"date":"2019-01-01", "temp":"cold", "season":"winter", "precip":"snow"},
  {"date":"2019-02-01", "temp":"cold", "season":"winter", "precip":"none"},
  {"date":"2019-03-01", "temp":"mild", "season":"spring", "precip":"rain"},
  {"date":"2019-04-01", "temp":"mild", "season":"spring", "precip":"none"},
  {"date":"2019-05-01", "temp":"warm", "season":"spring", "precip":"rain"},
  {"date":"2019-06-01", "temp":"warm", "season":"summer", "precip":"hail"},
  {"date":"2019-07-01", "temp":"hot", "season":"summer", "precip":"none"}
];

function transform(keyProp, valueProp, arr) {
  const keyValuePairs = arr
    .filter(function(obj) {
      const value = obj[valueProp];
      //only keep the value if it hasn't been encountered before
      const keep = !this.has(value);

      //add the value, so future repeats are removed
      this.add(value)

      return keep;
    }, new Set()) // <-- pass a Set to use as `this` in the callback
    .map(obj => [obj[keyProp], obj[valueProp]]);

  return new Map(keyValuePairs);
}

const map = transform("date", "precip", data);

//Stack Snippets don't print the Map content
//via console.log(map), so doing it manually
for (let [key, value] of map) {
  console.log(`${key} -> ${value}`);
}





请注意,这使用了.filter的第二个参数-它设置了回调的this上下文。通过将其设置为Set,可以确保仅用于.filter操作-您无需在整个函数范围内保留额外的变量。另外,由于它设置了this上下文,因此您需要普通的function而不是箭头功能,因为this的值不能更改。

关于javascript - 将Javascript数组简化为Map,从内部值创建键,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57292700/

10-11 22:20
查看更多