TransWikia.com

Пустой массив в результате рекурсии

Stack Overflow на русском Asked on November 13, 2021

Итак, у меня есть многомерный массив. К примеру:

var add_variants = [
["43", ["red", "green"]],
["44", ["small"]],
["48", ["metal","plastic"]]
];

Нужно сделать массив всех возможных вариантов такого типа:

[
    [
        ["43","red"], ["44", "small"], ["48", "metal"],
        ["43","green"], ["44", "small"], ["48", "metal"],
        ["43","red"], ["44", "small"], ["48", "plastic"],
        ["43","green"], ["44", "small"], ["48", "plastic"]
    ]
]

Я написал такой код:

var brute_array = function(arr, created_variant = []) { // перебираем все элементы входящего массива
    if (arr.length != 0) {
        let shifted = arr.shift(); // удаляем первую строку  
        created_variant = create_variant(shifted, created_variant); //создаем массив вариантов из данных удаленной строки
        brute_array(arr, created_variant); // рекурсия
    }
    return created_variant;
};

function create_variant(input_array, input_variant) {
    let return_variant = [];
    if ( input_array[1].length != 0 ) {
        for (var input_array_items of input_array[1]) { // перебор параметров
            if ( input_variant.length == 0 ) { // если массив вариантов пуст, то заполняем
                return_variant.push([ input_array[0], input_array_items] );
            }
            else { // иначе перебираем элементы и добавляем к каждому параметр
                for (var variant_items of input_variant) {
                    return_variant.push([variant_items, [input_array[0], input_array_items]] )
                }
            }
        }
    }
    return return_variant;
 }

 console.log(brute_array(input_variants));

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

Подскажите, где ошибка?

var brute_array = function(arr, created_variant = []) { // перебираем все элементы входящего массива
  if (arr.length != 0) {
    let shifted = arr.shift(); // удаляем первую строку  
    created_variant = create_variant(shifted, created_variant); //создаем массив вариантов из данных удаленной строки
    brute_array(arr, created_variant); // рекурсия
  }
  return created_variant;
};

function create_variant(input_array, input_variant) {
  let return_variant = [];
  if (input_array[1].length != 0) {
    for (var input_array_items of input_array[1]) { // перебор параметров
      if (input_variant.length == 0) { // если массив вариантов пуст, то заполняем
        return_variant.push([input_array[0], input_array_items]);
      } else { // иначе перебираем элементы и добавляем к каждому параметр
        for (var variant_items of input_variant) {
          return_variant.push([variant_items, [input_array[0], input_array_items]])
        }
      }
    }
  }
  return return_variant;
}

var add_variants = [
  ["43", ["red", "green"]],
  ["44", ["small"]],
  ["48", ["metal", "plastic"]]
];
console.log(brute_array(add_variants));

One Answer

Предварительно Вам нужно сделать из вашего массива объект.

const add_variants = [
  ["43", ["red", "green"]],
  ["44", ["small"]],
  ["48", ["metal","plastic"]]
];

const objVariants = Object.fromEntries(add_variants); 

Получится следующая структура:

{
  '43': [ 'red', 'green' ],
  '44': [ 'small' ],
  '48': [ 'metal', 'plastic' ]
}

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

const combinate = (obj) => {
  let combos = []; //  наш результат. В будущем массив с объектами.
  for (const key in obj) { // циклом обходим объект
    const values = obj[key]; // массивы со значениями, например ['red', 'green']
    const all = []; // вспомогательный массив

    for (let i = 0; i < values.length; i += 1) { // обходим каждое значение массива
      // тут самое интересное: обходим результирующий массив, 
      // чтобы создать правильный порядок комбинаций
      for (let j = 0; j < (combos.length || 1); j += 1) {
        // создаем комбинацию
        const newCombo = { ...combos[j], [key]: values[i] };
        all.push(newCombo);
      }
    }

    combos = all; // присваиваем вспомогательный массив результатирующему
    // для правильного порядка после каждого обхода ключа в объекте.
  }

  return combos;
}

Если будет непонятным, то просто возьмите листок с ручкой и пройдите все итерации, записывая, что получается. Или в редакторе поставьте точку остановы где-нибудь и проследите за значениями.

На выходе будет следующий массив:

[
  { '43': 'red', '44': 'small', '48': 'metal' },
  { '43': 'green', '44': 'small', '48': 'metal' },
  { '43': 'red', '44': 'small', '48': 'plastic' },
  { '43': 'green', '44': 'small', '48': 'plastic' }
]

И если Вы хотите в результате тот массив, который у Вас в примере, то пройдитесь циклом по нему и примените Object.entries на каждом объекте. Либо в реализации можно изменить строку генерации комбинации на эту:

const newCombo = [ ...(combos[j] || []), [key, values[i]] ];

Answered by letzabelin on November 13, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP