在总价格限制下生成产品组合

时间:2018-01-28 19:49:35

标签: javascript arrays algorithm combinations

我有一系列产品ID,以及2个数组,其中产品ID为key,价格和唯一标记值。

我希望在给定的总限价下拥有所有独特的产品组合:

  • 产品可以组合多次,除非它被标记为唯一
  • 组合应按产品ID
  • 排序
  • 有效组合是我们无法添加产品的组合

样品:

products = [1, 2, 3];

productPrices = {1:10, 2:15, 3:10};

productUnique = {1:true, 2:false, 3:false};

limitPrice = 40;

expected result = [[1,2,2],[1,2,3],[1,3,3,3],[2,2,3],[2,3,3],[3,3,3,3]];

如果可能,我如何在javascript中获得此结果? 谢谢你的帮助。

2 个答案:

答案 0 :(得分:0)

我建议您输入另一种格式,因此它是一个对象数组,其中每个对象都有idpriceunique属性。

然后使用该对象数组和限价,使用递归在每个递归级别选择要添加到一系列产品的产品,直到无法添加。此时将选定的产品列表添加到结果数组中。

在选择产品时,确定在下一级递归中仍然可以选择哪些产品:当选择了一种独特的产品时,不要将其作为选择可能性传递到下一级别。

为避免重复,一旦不再选择产品,请不要在更深的递归级别回复它;因此,当决定不再选择相同的产品时,在递归中传递较短的产品列表。当最便宜,仍然可用的产品比仍然可用的产品更贵时,递归结束。

这是一个片段:



function intoOne(products, productPrices, productUnique) {
    return products.map( (id) => ({
        id,
        price: productPrices[id],
        unique: productUnique[id]
    }));
}

function combinations(products, limitPrice) {
    const results = [];
    
    function recurse(sel, products, minPrice, maxPrice) {
        products = products.filter(p => p.price <= maxPrice);
        if (!products.length && minPrice > maxPrice) return results.push(sel);
        products.forEach( (p, i) => {
            recurse(sel.concat(p.id), products.slice(i+p.unique), 
                    minPrice, maxPrice-p.price);
            minPrice = Math.min(minPrice, p.price);
        });
    }
    
    recurse([], products, limitPrice, limitPrice);
    return results;
}

var products = [1, 2, 3],
    productPrices = {1:10, 2:15, 3:10},
    productUnique = {1:true, 2:false, 3:false},
    limitPrice = 40;
// Combine product characteristics in more suitable structure
products = intoOne(products, productPrices, productUnique);
// Call main algorithm
var result = combinations(products, limitPrice);
console.log(JSON.stringify(result));
&#13;
&#13;
&#13;

答案 1 :(得分:0)

您可以通过检查具有更改的索引或临时项的同一函数的下一次调用的和,长度和唯一参数来采用迭代和递归方法。

如果总和小于限制,则临时结果将添加到结果集中。

function iter(index, temp) {
    var product = products[index],
        sum = temp.reduce((s, k) => s + prices[k], 0);

    if (sum + prices[product] > limit) {
        result.push(temp);
        return;
    }

    if (!unique[product] || temp[temp.length - 1] !== product) {
        iter(index, temp.concat(product));
    }

    if (index + 1 < products.length) {
        iter(index + 1, temp);
    }
}

var products = [1, 2, 3],
    prices = { 1: 10, 2: 15, 3: 10 },
    unique = { 1: true, 2: false, 3: false },
    limit = 40,
    result = [];

iter(0, []);

console.log(JSON.stringify(result));