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" означает - в массиве.

Интересуют готовые решения - библиотеки или ссылки.
  • Вопрос задан
  • 174 просмотра
Решения вопроса 1
0xD34F
@0xD34F Куратор тега JavaScript
function setNestedVal(root, path, val) {
  const keys = path.split('.');
  const key = keys.pop();
  keys.reduce((acc, n) => acc[n] ??= {}, root)[key] = val;
}


setNestedVal(data, '0.arr.0.str', 'hello, world!!');
setNestedVal(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 Array
      ? data.map(n => replaceValues(n, test, transform))
      : data instanceof Object
        ? Object.fromEntries(Object
            .entries(data)
            .map(([ k, v ]) => [ k, replaceValues(v, test, transform) ])
          )
        : data;


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

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

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