【问题标题】:Merge objects updating duplicate keys (case-insensitively)合并更新重复键的对象(不区分大小写)
【发布时间】:2020-07-13 15:00:24
【问题描述】:

我正在使用具有配置对象的 javascript 模块。一个已经设置了默认值,用户可以传入值来覆盖这些设置值。我正在使用 Object.assign 来合并这两个对象。

这是一个例子:

const target = { a: 1, b: 2 }; // <-- default config
const source = { B: 4, c: 5 }; // <-- User input config 

Object.assign(target, source);

console.log(target); //{a: 1, b: 2, B: 4, c: 5}

在这个例子中,如果用户不小心输入了大写字母“B”而不是小写字母,那么当我真正想要更新的小写字母“b”时,配置对象会为其自身添加另一个值。 我知道这是 Object.assign 的预期行为,但试图让用户更容易做到这一点并且不区分大小写。

【问题讨论】:

  • 所以你需要创建一个循环遍历键并制作制服的方法。
  • 或者让用户一开始就做对了。
  • 您是否有混合大小写的字段名称、firstEntry 或类似的名称?

标签: javascript configuration


【解决方案1】:

此版本与其他版本略有不同。它只对初始对象中的键进行规范化,而其他键保持不变。像这样的:

insensitiveAssign ({a: 1, b: 2}, {B: 4, c: 5, D: 6}) //=> {a: 1, b: 4, c: 5, D: 6}
//                                                         ^     ^     ^     ^
//                                 unaltered --------------'     |     |     |
//                                 overwritten ------------------+     |     |
//                                 added ------------------------------+     |
//                                 added (note: key not modified) -----------+

这可能对你有用也可能没用,但它是解决问题的一种有趣的方法。它也不会修改您的任何一个对象,而是创建一个更改的克隆。

const insensitiveAssign = (target, source) => {
  const keys = Object .keys (target) .reduce ((a, k) => ((a[k.toLowerCase()] = k), a), {})
  return Object .entries (source) .reduce ((a, [k, v]) => {
    const lowerK = k.toLowerCase()
    const key = lowerK in keys ? keys[lowerK] : k
    a[key] = v;
    return a
  }, Object.assign({}, target)) // start with a shallow copy
}

  
const target = {a: 1, b: 2};
const source = {B: 4, c: 5, D: 6}; 

console .log (
  'result:',
  insensitiveAssign (target, source),
)
console .log (
  'target:', 
  target,
)
console .log (
  'source:',
  source
)

更新

评论更新了问题,询问如何将其应用于嵌套对象。实际上,我可能会尝试从头开始编写它,但是我现在没有时间,并且对此进行(仅经过轻微测试)修改似乎会起作用:

const insensitiveAssign = (target, source) => {
  // if-block added
  if (Object(target) !== target || (Object(source) !== source)) {
    return source
  }
  const keys = Object .keys (target) .reduce ((a, k) => ((a[k.toLowerCase()] = k), a), {})
  return Object .entries (source) .reduce ((a, [k, v]) => {
    const lowerK = k.toLowerCase()
    const key = lowerK in keys ? keys[lowerK] : k
    a[key] = insensitiveAssign(target[key], v); // this line updated
    return a
  }, Object.assign({}, target))
}

  
const target = {a: 1, b: 2, x: {w: 'a', y: {z: 42}}};
const source = {B: 4, c: 5, D: 6, x: {V: 'c', Y: {z: 101}}}; 

console .log (
  'result:',
  insensitiveAssign (target, source),
)
console .log (
  'target:', 
  target,
)
console .log (
  'source:',
  source
)

【讨论】:

  • 你的回答太棒了!如果我在配置中有一个嵌套对象,我需要更改什么?值会更新,但大小写不会持续存在。再次感谢!
【解决方案2】:

您必须先将对象键小写,例如完成here

const target = { a: 1, b: 2 }; // <-- default config
const source = { B: 4, c: 5 }; // <-- User input config 

const lowerSource = Object.keys(source).reduce((c, k) => (c[k.toLowerCase()] = source[k], c), {});

Object.assign(target, lowerSource);

console.log(target);

【讨论】:

    【解决方案3】:

    你可以简单地用Object.keys()Array.prototype.map()重新映射source对象的小写键,然后将生成的键值对作为参数传递给Object.assign()

    const target = { a: 1, b: 2 },
          source = { B: 4, c: 5 },
          
          result = Object.assign(
            target, 
            ...Object
              .keys(source)
              .map(key => 
                ({[key.toLowerCase()]: source[key]}))
          )
          
    console.log(result)

    【讨论】:

      【解决方案4】:

      你可以试试下面的代码。

      target = { a: 1, b: 2 }; // <-- default config
      source = { B: 4, c: 5 }; // <-- User input config 
      
      source = JSON.parse(JSON.stringify(source).toLowerCase())
      
      Object.assign(target, source);
      

      【讨论】:

      • 一个危险的解决方案,因为它也会改变关键的,这可能会也可能不会。它也会遭受字符串化/重新解析的开销,尽管这可能不是一个大问题。
      • 是的,戴夫,我想展示一种不同的方式。我的错误并没有增加它的负面部分。使用 stringify 的另一个缺点是它会忽略对象中的函数。
      猜你喜欢
      • 2020-07-19
      • 2013-08-19
      • 2016-12-25
      • 1970-01-01
      • 2017-07-13
      • 1970-01-01
      • 2014-02-05
      • 2011-02-11
      • 2013-10-06
      相关资源
      最近更新 更多