Есть несколько вопросов с ответами на StackOverflow, который показывает, как найти декартово произведение для различных простых массивов. И замечательная статья о RosettaCode . Но я не могу найти решение своей проблемы.
У меня есть массив объектов с элементами, назовем его items
:
let items = [{
id: 1
quantity: 2
field: "other_field"
},
{
id: 2
quantity: 3
field: "other_field"
}]
Каждый элемент в этом массиве имеет метод ценообразования / изготовления, и мы можем получить его по запросу.
let pricing = getPricing(id) //item id
/*
Which will return to us:
*/
pricing = [
{pricing_id: 1, reagent_items: [/*array of objects, fields exactly items*/]},
{pricing_id: 2, reagent_items: [/*array of objects, fields exactly items*/]}
]
ПРОБЛЕМА КАРТЕЗИЙСКОГО ПРОДУКТА:
Как вы, возможно, уже поняли, по заголовку ответа я хочу получить все возможные комбинации предметов И reagent_items из цены методы.
Например, если у нас есть два элемента и у каждого элемента (из этих 2) только один метод ценообразования, будет 4 различных комбинации:
- 2 элементов по умолчанию с
items
- первый элемент по умолчанию с
items
(item[0]
) и все все reagent_items с getPricing
для item[1]
- второй элемент по умолчанию с
items
(item[1]
) и все все reagent_items от getPricing
для item[0]
- оба reagent_items от
getPricing
для обоих по умолчанию items
Я буквально не могу sh reagent items
до items
(или удалить элемент из items
) массива, потому что элементы могут То же самое (включая друг друга) Вместо этого Я использую свой собственный Array.prototype.method
для добавления / удаления элементов из массива items
. Он делает то же самое, что и push
/ slice
, но более элегантно, манипулируя полями id
и quantity
.
Фактическая проблема заключается в области arrays.length и for ... loop
.
Когда мы оцениваем декартово произведение по умолчанию, мы знаем его перед array.length и его элементами. Но в моем случае я должен getPricing
каждый элемент, а затем получить массив методов ..
Схема:
Это как:
Default: I_1 I_2 ... N
/ \ / \ / \
Get Pricing: [I_A, I_B][I_B, I_C] [IN_J, IN_K],
[IN_Y, IN_X, IN_Z],
Таким образом, речь идет не о поиске: Cartesian([I_A, I_B],[I_B, I_C])
, а о чем-то вроде:
I_1 + I_2
I_1 + (I_B, I_C)
(I_A, I_B) + I_2
(I_A, I_B) + (I_B, I_C)
...
Таким образом, элемент по умолчанию включает друг друга и их reagent_items
, и легко найти все комбинации двух элементов, но когда он станет 3 + ..
Мой текущий псевдокод на данный момент:
/* inside async*/
...
let ArrayOfPricing = [] //length 2, where each Array represent Array of `pricing` for each item
Promise.all(items.map(async item => {
const itemPricing = await getPricing(item.id);
ArrayOfPricing.push(itemPricing );
})
/**And what's next? **/
for (let item of items) {
}
Так что я не могу понять, что мне делать дальше, на этом этапе.
- Должен ли я повторять / повторять каждый элемент? Но если это так, даже если я итерирую каждый элемент один за другим, меняю / удаляю его и добавляю его reagent_items (для каждой цены), я все равно не изменяю следующий элемент / элемент в массиве
items
, а его длина больше затем просто 2, тогда я не получу все комбинации, это будет выглядеть так:
for items
↓
item[1] → for pricing
→ for reagent_items
↓
replace item[1] for all reagent_item
item[2] /** they are still there, but I need iterate over it's pricing , too **/
item[3]
- или я мог бы рассчитать все возможные комбинации, посмотрев на длину
items
и все pricing
длина, а затем сформировать и очистить новый массив с фиксированной длиной и pu sh для всех комбинаций. Но если я повторю его для pu sh с for loop
... Я должен объединить элементы, и это будет for loop, inside for loop, inside for .. loop
..
Так что, честно говоря, у меня нет идей. Я не прошу писать полный рабочий код вместо меня, но указываю мне выход из этого l oop. Как получить каждую комбинацию для каждого предмета и «детских предметов» внутри него? Сколько циклов я должен использовать тогда? Я буду благодарен за любую полезную ссылку идея / псевдокод / пост, которая поможет мне разобраться с этим делом. Я также здесь и проверю все комментарии и ответы ниже.
UPD простая версия «от того, что я получаю, к тому, что я хочу»
от это:
[
{
field: "original, can be cloned for every combination",
items:
[
{id: 1, quantity: 2},
{id: 2, quantity: 3}
]
}
]
до:
[
{
field: "original",
items:
[
{id: 1, quantity: 2},
{id: 2, quantity: 3}
]
},
{
field: "combination1",
items:
[
{id: 11, quantity: 1}, //from getPricing(item[0])
{id: 12, quantity: 1}, //from getPricing(item[0])
{id: 2, quantity: 3}
]
},
{
field: "combination2",
items:
[
{id: 1, quantity: 2},
{id: 22, quantity: 3} //from getPricing(item[1])
{id: 23, quantity: 3} //from getPricing(item[1])
]
},
{
field: "combination3",
items:
[
{id: 11, quantity: 1}, //from getPricing(item[0])
{id: 12, quantity: 1}, //from getPricing(item[0])
{id: 22, quantity: 3} //from getPricing(item[1])
{id: 23, quantity: 3} //from getPricing(item[
]
}
//can be any length according to getPricing of every item, and I modify original array, but we could create a new one.
]