Преобразовать массив объектов в вложенный объект в Javascript - PullRequest
0 голосов
/ 07 сентября 2018

Я хотел бы преобразовать массив объектов во вложенный объект, используя рекурсивную функцию.

Цель состоит в том, чтобы создать функцию, которая работает независимо от глубины моего начального массива. Ниже вы можете увидеть исходные данные с желаемым результатом + фрагмент кода с попыткой решить эту проблему.

Начальный массив объектов

configurator: [
  {
    key: '-LLnLuLt6cn-vBpMWv-u',
    name: 'CONFIGURATOR_1',
    collections: [
      {
        key: '-LLnMWy69vACjys0QIGH',
        name: 'COLLECTION_1',
        options: [
          {
            key: '-LLnOxg5hsDYR-PcfjBT',
            name: 'OPTION_1',
          },
          {
            key: '-LLnP-O6TyHxIpPk9bCU',
            name: 'OPTION_2',
          },
        ],
      },
      {
        key: '-LLnMYNyJmhSCPB-8lL1',
        name: 'COLLECTION_2',
      },
    ],
  },
  { key: '-LLnLtLs7PjXSAW0PWCQ',
    name: 'CONFIGURATOR_2',
  }]

Желаемый результат: вложенные объекты

configurator: {
  '-LLnLuLt6cn-vBpMWv-u': {
    name: 'CONFIGURATOR_1',
    index: 0,
    collections: {
      '-LLnMWy69vACjys0QIGH': {
        name: 'COLLECTION_1',
        index: 0,
        options: {
          '-LLnOxg5hsDYR-PcfjBT': {
            name: 'OPTION_1',
            index: 0,
          },
          '-LLnP-O6TyHxIpPk9bCU': {
            name: 'OPTION_2',
            index: 1,
          },
        },
      },
      '-LLnMYNyJmhSCPB-8lL1': {
        name: 'COLLECTION_2',
        index: 1,
      },
    },
  },
  '-LLnLtLs7PjXSAW0PWCQ': {
    name: 'CONFIGURATOR_2',
    index: 1,
  },
}

Моя попытка

Вот фрагмент кода того, что я пробовал до сих пор. Работает только с первой глубиной массива. Я считаю, что это проблема, которую нужно решить: как динамически добавить / «толкнуть» объект к вложенному объекту?

Надеюсь, кто-нибудь может помочь. Ура, Жюльен.

const data = {
  configurator: [{
      key: '-LLnLuLt6cn-vBpMWv-u',
      name: 'CONFIGURATOR_1',
      collections: [{
          key: '-LLnMWy69vACjys0QIGH',
          name: 'COLLECTION_1',
          options: [{
              key: '-LLnOxg5hsDYR-PcfjBT',
              name: 'OPTION_1',
            },
            {
              key: '-LLnP-O6TyHxIpPk9bCU',
              name: 'OPTION_2',
            },
          ],
        },
        {
          key: '-LLnMYNyJmhSCPB-8lL1',
          name: 'COLLECTION_2',
        },
      ],
    },
    {
      key: '-LLnLtLs7PjXSAW0PWCQ',
      name: 'CONFIGURATOR_2',
    }
  ]
};


const format = (object) => {
  const result = {};
  Object.keys(object).forEach((property) => {
    if (Array.isArray(object[property])) {
      object[property].forEach((test, index) => {
        const {
          key,
          ...content
        } = test;
        result[key] = {
          index,
          ...content
        };
        format(content);
      });
    }
  });
  return result;
};

const formated = format(data);
console.log('@FORMATED__', formated);

Ответы [ 2 ]

0 голосов
/ 07 сентября 2018

Отредактированный

function format(data) {
  var result = {};

  data.forEach(function(config, i) {
    var obj = {
        index: i
    }

    Object.keys(config)
        .forEach(function(key) {
            if (!Array.isArray(config[key])) {
                if (key != "key") obj[key] = config[key];
            } else {
                obj[key] = format(config[key]);
            }
        });

    result[config.key] = obj;
  });

  return result;
}
console.log(format(data));
0 голосов
/ 07 сентября 2018

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

const format = array => 
    array.reduce((acc, obj, index) => {
        const {key, ...rest} = obj;
        Object.keys(rest)                                            // get the keys of the rest of the object
              .filter(key => Array.isArray(rest[key]))               // filter those that have arrays as values
              .forEach(key => rest[key] = format(rest[key]));        // for each one of them, format their array and assign them back to the rest object
        acc[key] = { ...rest, index };                               // create the new object and assign it to the accumulator
        return acc;
    }, {});

Пример:

const format = array => 
    array.reduce((acc, obj, index) => {
        const {key, ...rest} = obj;
        Object.keys(rest)
              .filter(key => Array.isArray(rest[key]))
              .forEach(key => rest[key] = format(rest[key]));
        acc[key] = { ...rest, index };
        return acc;
    }, {});

const arr = [{"key":"-LLnLuLt6cn-vBpMWv-u","name":"CONFIGURATOR_1","collections":[{"key":"-LLnMWy69vACjys0QIGH","name":"COLLECTION_1","options":[{"key":"-LLnOxg5hsDYR-PcfjBT","name":"OPTION_1"},{"key":"-LLnP-O6TyHxIpPk9bCU","name":"OPTION_2"}]},{"key":"-LLnMYNyJmhSCPB-8lL1","name":"COLLECTION_2"}]},{"key":"-LLnLtLs7PjXSAW0PWCQ","name":"CONFIGURATOR_2"}];

console.log(format(arr));

Примечание: Если, например, могут быть некоторые массивы, которые не содержат только объекты, которые вы хотите пропустить, просто измените фильтрацию с:

.filter(key => Array.isArray(rest[key]))

Кому:

.filter(key => Array.isArray(rest[key]) && rest[key].every(item => item && typeof item === "object"))

Который проверяет, содержит ли массив только объекты, прежде чем применять format к нему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...