2 Вопрос: Добавить значение к объекту с глубиной его ключа на основе массива

вопрос создан в Thu, May 2, 2019 12:00 AM

У меня есть массив. Скажем так:

const array = ["lvl1", "lvl2", "lvl3", "key"]

У меня есть ценность. Скажем так:

const value = false

У меня есть объект. Скажем так:

const object = {
  lvl1: {
    dogs: "bark",
    lvl2: {
      cats: "meow",
      lvl3: {
        cows: "moo"
        key: true
      }
    }
  }
}

Как создать функцию, которая принимает array и value, а затем обновляет объект, так что key в массиве (последний элемент в массиве) обновляется с новым value? Он должен быть надлежащим образом вложен на основе первых строк array.length - 1 в массиве.

Например, давайте вызвали функцию createObject. Если я вызываю ее с помощью array и value, уже определенных выше, как:

const newObject = createObject(array, value)

Тогда newObject должен быть равен:

{
  lvl1: {
    dogs: "bark",
    lvl2: {
      cats: "meow",
      lvl3: {
        cows: "moo"
        key: false
      }
    }
  }
}

Вот еще один пример с другим уровнем вложенности:

const updatedObject = createObject(["lvl1", "lvl2", "cats"], "stink")

Тогда updatedObject должен быть равен:

{
  lvl1: {
    dogs: "bark",
    lvl2: {
      cats: "stink",
      lvl3: {
        cows: "moo"
        key: true
      }
    }
  }
}

Я зашел так далеко, но это не работает:

import object from "./object"

const createObject = (array, value) => {
  let results = object;
  for (let i = 0; i < array.length; i++) {
    i === array.length - 1
      ? (results = results[array[i]] = {
          ...results[array[i]],
          [array[i]]: value
        })
      : (results = results[array[i]] = {
          ...results[array[i]],
          [results[array[i]]]: {}
        });
    }
  return results;
}

Я не хочу менять исходный объект. Я хочу вернуть новый объект. И я не буду добавлять какие-либо новые пары ключ /значение к объекту, только изменяя существующие пары ключ /значение.

    
1
  1. вы хотите получить новый независимый объект?
    2019-05-02 15: 19: 17Z
  2. Да, я не хочу изменять существующий объект. Фактически существующий объект - это состояние в моем приложении React, поэтому я не хочу изменять его напрямую.
    2019-05-02 15: 21: 22Z
2 ответа                              2                         

Это немного более обобщенно, поскольку не предполагает, что источником является глобальная переменная с именем object:

р>

let array = ["lvl1", "lvl2", "lvl3", "key"];
let value = false;

let createObject = (keys, value) => {
  let o, obj = o = {};
  let lastKey = keys.pop();
  keys.forEach(key => o = o[key] = o[key] || {});
  o[lastKey] = value;
  return obj;
};

let addToObject = (obj, keys, value) => {
  let o, copy = o = JSON.parse(JSON.stringify(obj));
  let lastKey = keys.pop();
  keys.forEach(key => o = o[key] = o[key] || {});
  o[lastKey] = value;
  return copy;
};

let x = createObject(array, value);
let y = addToObject(x, ['lvl1'], 3);
let z = addToObject(y, ['a', 'b', 'c'], 4);

console.log(x);
console.log(y);
console.log(z);
    
2
2019-05-02 16: 34: 28Z
  1. К сожалению, это не работает. codepen.io/JakeIQ/pen/bJXwLO
    2019-05-02 15: 55: 31Z
  2. Запустив как приведенный выше фрагмент, так и ваш фрагмент кода, я вижу ожидаемые результаты (такие же, как в вашем комментарии).
    2019-05-02 16: 03: 55Z
  3. Вы правы, взломанный кодовый блок отрезал консоль в консоли браузера. Если я проверю консоль на Chrome, она там. Спасибо! Я отмечу это как правильный ответ и дополню свой пост окончательным кодом, который я использовал, чтобы получить мои точные требования.
    2019-05-02 16: 12: 18Z
  4. Хотя одна проблема, которую я заметил, заключается в том, что o не определено в addToObject.
    2019-05-02 16: 25: 48Z
  5. Я не получаю эту ошибку в Chrome, но вы правы, let a = b = 0 объявляет a, но не b. Обновил мой ответ, чтобы явно объявить o .
    2019-05-02 16: 34: 43Z

    Вы можете взять записи и построить новый объект и проверить, равен ли фактический ключ первому элементу массива, а затем проверить длину остального массива и принять значение. Для вложенной копии проверьте объект и создайте новый более глубокий уровень, вызвав функцию еще раз.

    р>

    function getObject(object, [key, ...keys], value) {
        return Object.assign({}, ...Object
            .entries(object)
            .map(([k, v ]) => ({ [k]: k === key && !keys.length
                ? value
                : v && typeof v === 'object'
                    ? getObject(v, k === key ? keys : [], value)
                    : v
            })),
            Object.keys(object).includes(key) || { [key]: keys.length
                ? getObject({}, keys, value)
                : value
            }
        );
    }
    
    const
        object1 = { lvl1: { dogs: "bark", lvl2: { cats: "meow", lvl3: { cows: "moo", key: true } } } },
        object2 = getObject(object1, ["lvl1", "lvl2", "lvl3", "key"], false),
        object3 = getObject(object2, ["lvl1", "lvl2", "cats"], "stink"),
        object4 = getObject({}, ["lvl1", "lvl2", "cats"], "stink");;
    
    console.log(object1);
    console.log(object2);
    console.log(object3);
    console.log(object4);
    .as-console-wrapper { max-height: 100% !important; top: 0; }
        
    0
    2019-05-02 17: 10: 56Z
источник размещен Вот