合并对象更新重复键(不区分大小写)
Merge objects updating duplicate keys (case-insensitively)
我正在使用具有配置对象的 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 的预期行为,但试图让用户更容易做到这一点并且不区分大小写。
您必须先将对象键小写,就像完成的那样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);
您可以简单地重新映射 source
对象,将其键小写为 Object.keys()
and Array.prototype.map()
, then pass resulting key-value pairs as parameter to 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)
您可以尝试类似下面的代码。
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);
这个版本与其他版本略有不同。它仅规范化在初始对象中找到的键,而其他键保持不变。像这样:
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
)
我正在使用具有配置对象的 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 的预期行为,但试图让用户更容易做到这一点并且不区分大小写。
您必须先将对象键小写,就像完成的那样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);
您可以简单地重新映射 source
对象,将其键小写为 Object.keys()
and Array.prototype.map()
, then pass resulting key-value pairs as parameter to 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)
您可以尝试类似下面的代码。
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);
这个版本与其他版本略有不同。它仅规范化在初始对象中找到的键,而其他键保持不变。像这样:
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
)