在StackOverflow上有几个问题与答案,展示了如何为各种简单数组寻找笛卡尔积。还有一篇关于 罗塞塔代码. 但我找不到任何解决我的问题的方法。
我有一个包含项目的数组对象,我们称它为 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*/]}
]
你可能已经明白了,根据答案的标题,我想收到所有可能的项目组合。AND reagent_items from pricing methods.
例如,如果我们有两个项目,而每个项目(其中2个)都只有一种定价方法,那么将有4种不同的组合。
items
items
(item[0]
)和所有的试剂_项目从 getPricing
对于 item[1]
items
(item[1]
)和所有的试剂_项目从 getPricing
对于 item[0]
getPricing
对于两个默认 items
我真的推不动
reagent items
到items
(或从items
)数组,因为项目可以相同(互相包含)代替它。我是用自己的Array.prototype.method
用于添加删除项目,从items
阵列。它的作用就像push
slice
但以更优雅的方式,用id
和quantity
字段。
实际的问题在于arrays.length和 for ... loop
.
当我们评估默认的笛卡儿乘积时,我们在数组.长度和它的元素之前就知道了,但在我的例子中,我应该 getPricing
每一个项目,然后接收数组方法。
Schema。
就像..:
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) {
}
所以我不明白在这个阶段我应该做什么。
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
长度,然后形成固定长度的新数组并清空,然后推送给所有组合。但是,如果我用 for loop
... 我应该合并项目,这将是 for loop, inside for loop, inside for .. loop
..所以说实话,我是没有办法了。我不要求你代替我写出完整的工作代码,而是给我指出这个循环的出路。如何得到每一个项目的每一个组合和里面的 "宝贝项目"?那我应该用多少个循环?如果有什么有用的ideapseudocodepost链接,能帮助我处理这个案例,我将感激不尽。我也在这里,会查看下面所有的评论和答案。
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.
]
正如我所承诺的,我已经找到了我的问题的解决方案,我想与StackOverflow社区分享。
伪代码。
let array = [
{
field: "original, can be cloned for every combination",
items:
[
{id: 1, quantity: 2},
{id: 2, quantity: 3}
]
}
]
for (let element of array) {
let MethodsCombinations = [];
for await (let forCombinations of element.items.map((item, i) => {
return getMethod(item.id) //get Method for each item)
})) {
MethodsCombinations.push(forCombinations)
}
/* Cartesian product */
let vanilla_CartesianProduct = MethodsCombinations.reduce((a, b) => a.reduce((r, v) => r.concat(b.map(w => [].concat(v, w))), []));
/* Return array of arrays, with objects inside like default array */
/**
* Other logic with two for loops and merging all the combinations and quantities
* with (my own) modified Array.prototype.addItemToArray
*/
}
我非常感谢这个 Nina Scholz的回答 和 她的真棒StackOverflow 的所有答案的组合spermutations的个人资料,并提供支持。