Задать вопрос
maksipes
@maksipes

Как изменить значение в объекте по его пути?

Есть массив объектов, в котором большая вложенность, в том числе и через массивы. Например:

export const data = [
  {
    created_at: "30.08.2021",
    entry: {
      created_at: "30.08.2021",
    },
    arr: [
      {
        id: 111,
        created_at: "30.08.2021",
        updated_at: "30.08.2021",
        subEntry: {
          id: 222,
          created_at: "30.08.2021",
          updated_at: null,
          date_assigned_on: "09.09.2021",
          date_prepared_for: "10.09.2021",
        }
      }
    ]
  }
];

Нужно изменить этот массив, преобразовав все строки с датами в нём, независимо от того, как глубоко они вложены, в объекты.

Поскольку полагаться на название ключей нельзя, есть идея использовать PATHs, например так:

[
  'created_at',
  'entry.created_at',
  'arr.0.created_at',
  'arr.0.subEntry.updated_at',
]

Т.е., перечисляем все значения, которые надо преобразовать. При этом "0" означает - в массиве.

Интересуют готовые решения - библиотеки или ссылки.
  • Вопрос задан
  • 221 просмотр
Подписаться 1 Простой 2 комментария
Помогут разобраться в теме Все курсы
  • Нетология
    Fullstack-разработчик на Python + нейросети
    20 месяцев
    Далее
  • Skillfactory
    Профессия Веб-разработчик
    12 месяцев
    Далее
  • Академия Eduson
    Fullstack-разработчик на JavaScript
    11 месяцев
    Далее
Решения вопроса 1
0xD34F
@0xD34F Куратор тега JavaScript
Вот так:

function setNested(root, ...args) {
  const val = args.pop();
  const key = (args = args
    .flat(Infinity)
    .flatMap(n => typeof n === 'string' ? n.split('.') : n))
    .pop();

  args.reduce((p, c) => p[c] ??= {}, root)[key] = val;
}

setNested(data, '0.arr.0.str', 'hello, world!!');
setNested(data, 0, 'arr', 1, 'num', 666);

Интересуют готовые решения

https://lodash.com/docs/4.17.15#set

А вообще, учитывая что за задачу вы пытаетесь решить...

Нужно изменить этот массив, преобразовав все строки с датами в нём, независимо от того, как глубоко они вложены, в объекты.

...вам ничего из того, что выше, не нужно. Делаем функцию, которая рекурсивно обойдёт переданный объект, проверяя, чем являются значения - если строкой с датой, то выполняет указанное преобразование:

const replaceValues = (data, test, transform) =>
  test(data)
    ? transform(data)
    : data instanceof Object
      ? Object.entries(data).reduce((acc, [ k, v ]) => (
          acc[k] = replaceValues(v, test, transform),
          acc
        ), data.constructor())
      : data;

const newData = replaceValues(
  data,
  x => typeof x === 'string' && /^\d{2}\.\d{2}\.\d{4}$/.test(x),
  str => new Date(str.split('.').reverse().join('-'))
);
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы