Объединить объекты, обновляя повторяющиеся ключи (без учета регистра) - PullRequest
0 голосов
/ 13 июля 2020

Я использую модуль 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» вместо строчной one, то объект конфигурации добавляет себе еще одно значение, когда мне действительно нужно обновить строчную букву «b». Я знаю, что это предполагаемое поведение Object.assign, но пытаюсь упростить его для пользователя и не учитывать регистр.

Ответы [ 4 ]

1 голос
/ 13 июля 2020

Эта версия немного отличается от других. Он нормализует только ключи, найденные в исходном объекте, оставляя остальные нетронутыми. Примерно так:

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
)
1 голос
/ 13 июля 2020

Вы можете просто переназначить объект source в нижнем регистре его ключей с помощью Object.keys() и Array.prototype.map(), а затем передать полученные пары ключ-значение в качестве параметра в 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)
1 голос
/ 13 июля 2020

Сначала вам нужно будет ввести клавиши объекта в нижний регистр, как это сделано здесь

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);
0 голосов
/ 13 июля 2020

Вы можете попробовать что-то вроде кода ниже.

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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...