【问题标题】:Merging Objects with Like Terms合并具有相似术语的对象
【发布时间】:2016-11-21 15:33:40
【问题描述】:

我目前正在尝试按各种特征将数据集组合在一起。我正处于练习的最后一部分,即:

转动这个:

[
  {
    "AU": {
      "iOS": 1
    }
  },
  {
    "US": {
      "iOS": 2
    }
  },
  {
    "CA": {
      "iOS": 1
    }
  },
  {
    "US": {
      "Android": 1
    }
  },
  {
    "DO": {
      "Android": 1
    }
  }
]

进入这个:

[
  {
    "AU": {
      "iOS": 1
    }
  },
  {
    "US": {
      "iOS": 2,
      "Android": 1
    }
  },
  {
    "CA": {
      "iOS": 1
    }
  },
  {
    "DO": {
      "Android": 1
    }
  }
]

换句话说,groupBy CountryCode 并保留各自的 iOS 或 Android 标签。另外,请记住,不允许计算密钥。 Computed Keys 任何帮助将不胜感激。

【问题讨论】:

  • 如果同一国家/地区存在两个“iOS”或 Android 条目怎么办?解决方案是否必须基于函数式编程?
  • 该数据集之前的数据集将累积这些值,因此我们不必担心这种情况下存在重复集。 Underscore.js 用于 groupBy 一个键,然后 groupBy 再次使用另一个键。数据即将存储,只需要组织,这是最后一步;合并基于类似的国家代码。函数式编程不是强制性的。

标签: javascript arrays node.js functional-programming javascript-objects


【解决方案1】:

使用一点 omap 助手和 Object.assign 这是一个非常简单的任务

let input = [
  { "AU": { "iOS": 1 } },
  { "US": { "iOS": 2 } },
  { "CA": { "iOS": 1 } },
  { "US": { "Android": 1 } },
  { "DO": { "Android": 1 } }
]

let omap = (o,f)=>
  Object.keys(o).reduce((acc, k)=>
    Object.assign(acc, { [k]: f(o[k], k, o) }), {})

var output = input.reduce((acc, x) =>
  Object.assign(acc, omap(x, (v, k)=>
    acc[k] === undefined
      ? v
      : Object.assign({}, acc[k], v))), {})

console.log(output)

说明

omap 允许您像映射数组一样映射对象

let omap = (o,f)=>
  Object.keys(o).reduce((acc, k)=>
    Object.assign(acc, { [k]: f(o[k], k, o) }), {})

omap({a:1, b:2, c:3}, x=> x*x)
//=> {a:1, b:3, c:9}

使用omap,我们可以遍历每个输入并将键映射到最终输出对象

// reduce the list of inputs by ...
var output = input.reduce((acc, x) =>
  // assigning to the final output, the omap'd input
  Object.assign(acc, omap(x, (v, k)=>
    // if the final output doesn't have a matching key
    acc[k] === undefined
      // return the input's value
      ? v
      // otherwise return the existing final output merged with the input value
      : Object.assign({}, acc[k], v))), {})

console.log(output)

【讨论】:

    【解决方案2】:

    在完全原生的 JavaScript 中 -

    input.forEach(function(item){
        Object.keys(item).forEach(function(country){
            var systems = item[country]
            if (!obj[country]) obj[country] = {}
            Object.keys(systems).forEach(function(system){
                if (!obj[country][system]) obj[country][system] = item[country][system]
                else obj[country][system] += item[country][system]
            })
        })
    })
    

    如果您可以使用库(例如 Underscore 或 JQuery),您也可以收紧语法

    【讨论】:

    • 如果这不属于您不使用计算密钥的限制,但您提前知道密钥是什么,那就更容易了。
    • 非常感谢您的帮助!很好地使用 Object.keys,因为它不会遍历原型链。谢谢! @larz
    【解决方案3】:

    我不确定你所说的不允许计算密钥是什么意思,但我已经在 https://jsfiddle.net/ezrajr/z35q9s3h/ 上为此设置了一个 jsfiddle

    这会将您的数据数组转换为数据对象,这意味着您不必再知道索引了。您可以使用字符串访问器表示法直接访问数据:

    data['US']['iOS'];
    

    或点表示法:

    data.US.iOS;
    

    其中任何一种都适用于访问数据,但通常在您知道键时使用点表示法,而在动态设置键时使用字符串表示法。

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-20
    • 1970-01-01
    • 1970-01-01
    • 2019-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多