产品SKU设计与笛卡尔积-Javascript版

什么是笛卡尔积

笛卡尔乘积是指在数学中,两个集合X和Y的笛卡尓积(Cartesian product),又称直积,表示为X×Y,第一个对象是X的成员而第二个对象是Y的所有可能有序对的其中一个成员。

例如:

假设集合A={a,b},集合B={0,1,2},则两个集合的笛卡尔积为:

{(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)}.

在Javascript中的实现

为数组增加一个分块方法

/**
 * 把一个数组分割成新的数组块
 * @param data
 * @param size
 *
 * chunk(['a', 'b', 'c', 'd'], 2);
 * // => [['a', 'b'], ['c', 'd']]
 *
 * chunk(['a', 'b', 'c', 'd'], 3);
 * // => [['a', 'b', 'c'], ['d']]
 */
const chunk = function (data: any[], size: number = 1): any[][] {
    size = Math.max(+size || 1, 1);
    let index = 0;
    let resIndex = -1;
    const length = data.length;
    const result = Array(Math.ceil(length / size));

    while (index < length) {
        result[++resIndex] = data.slice(index, (index += size));
    }
    return result;
};

基础实现

function descartes(t: any[]){
    let a = t.shift(),
        r,
        b;
    !(a.constructor === Array) && (a = [a]);
    a = chunk(a, 1);
    do{
        r = [];
        b = t.shift();
        !(b.constructor === Array) && (b = [b]);
        a.forEach( function(p) {
            chunk(b, 1).forEach( function(q) {
                r.push(p.concat(q));
            });
        });
        a = r;
    }while(t.length > 0);
    return r;
}

let arr = [
    ['黑色','红色'],
    ['透气','防滑'],
    ['37码','38码','39码']
];
console.log(descartes(arr));

输出

[
  [ '黑色', '透气', '37码' ],
  [ '黑色', '透气', '38码' ],
  [ '黑色', '透气', '39码' ],
  [ '黑色', '防滑', '37码' ],
  [ '黑色', '防滑', '38码' ],
  [ '黑色', '防滑', '39码' ],
  [ '红色', '透气', '37码' ],
  [ '红色', '透气', '38码' ],
  [ '红色', '透气', '39码' ],
  [ '红色', '防滑', '37码' ],
  [ '红色', '防滑', '38码' ],
  [ '红色', '防滑', '39码' ]
]

扩展到项目

interface SkuUnitStruct {
    attrId?: string;
    attrName: string;
    optionId?: string;
    optionName: string;
    name: string;
}

/**
 * 根据属性和属性的选项 计算笛卡尔积
 * @param attrWithOptions
 */
function calcDescartes(attrWithOptions: any[]): any[][] {
    if (attrWithOptions.length < 1) {
        return [];
    }
    attrWithOptions.forEach((attr) => {
        attr.options.forEach((option) => {
            option.attr_id = attr.id as string;
            option.attr_name = attr.name;
        });
    });
    const attrs: any[] = JSON.parse(
        JSON.stringify(attrWithOptions)
    );

    const firstAttr = attrs.shift();
    let secondAttr: any;

    let firstOptionChucks: any[][] = chunk(firstAttr.options, 1);
    let result: any[][] = firstOptionChucks;

    while (attrs.length > 0) {
        result = [];
        secondAttr = attrs.shift();
        const secondOptionChucks: any[][] = chunk(
            secondAttr.options,
            1
        );
        firstOptionChucks.forEach(function (previousOptions) {
            secondOptionChucks.forEach(function (currentOptions) {
                result.push(previousOptions.concat(currentOptions));
            });
        });
        firstOptionChucks = result;
    }
    return result;
}

let attrWithOptions =  [
    {
        "id": "", "name": "运营商", "options": [
            { "id": "", "name": "电信", "attr_id": "", "attr_name": "运营商" },
            { "id": "", "name": "移动", "attr_id": "", "attr_name": "运营商" },
            { "id": "", "name": "联通", "attr_id": "", "attr_name": "运营商" }
        ]
    },
    {
        "id": "", "name": "网络", "options": [
            { "id": "", "name": "4G", "attr_id": "", "attr_name": "网络" },
            { "id": "", "name": "5G", "attr_id": "", "attr_name": "网络" }
        ]
    },
    {
        "id": "", "name": "颜色", "options": [
            { "id": "", "name": "黑色", "attr_id": "", "attr_name": "颜色"},
            { "id": "", "name": "白色", "attr_id": "", "attr_name": "颜色" }
        ]
    }
];

console.log(calcDescartes(attrWithOptions));

输出

[
  [
    { id: '', name: '电信', attr_id: '', attr_name: '运营商' },
    { id: '', name: '4G', attr_id: '', attr_name: '网络' },
    { id: '', name: '黑色', attr_id: '', attr_name: '颜色' }
  ],
  [
    { id: '', name: '电信', attr_id: '', attr_name: '运营商' },
    { id: '', name: '4G', attr_id: '', attr_name: '网络' },
    { id: '', name: '白色', attr_id: '', attr_name: '颜色' }
  ],
  [
    { id: '', name: '电信', attr_id: '', attr_name: '运营商' },
    { id: '', name: '5G', attr_id: '', attr_name: '网络' },
    { id: '', name: '黑色', attr_id: '', attr_name: '颜色' }
  ],
  [
    { id: '', name: '电信', attr_id: '', attr_name: '运营商' },
    { id: '', name: '5G', attr_id: '', attr_name: '网络' },
    { id: '', name: '白色', attr_id: '', attr_name: '颜色' }
  ],
  [
    { id: '', name: '移动', attr_id: '', attr_name: '运营商' },
    { id: '', name: '4G', attr_id: '', attr_name: '网络' },
    { id: '', name: '黑色', attr_id: '', attr_name: '颜色' }
  ],
  [
    { id: '', name: '移动', attr_id: '', attr_name: '运营商' },
    { id: '', name: '4G', attr_id: '', attr_name: '网络' },
    { id: '', name: '白色', attr_id: '', attr_name: '颜色' }
  ],
  [
    { id: '', name: '移动', attr_id: '', attr_name: '运营商' },
    { id: '', name: '5G', attr_id: '', attr_name: '网络' },
    { id: '', name: '黑色', attr_id: '', attr_name: '颜色' }
  ],
  [
    { id: '', name: '移动', attr_id: '', attr_name: '运营商' },
    { id: '', name: '5G', attr_id: '', attr_name: '网络' },
    { id: '', name: '白色', attr_id: '', attr_name: '颜色' }
  ],
  [
    { id: '', name: '联通', attr_id: '', attr_name: '运营商' },
    { id: '', name: '4G', attr_id: '', attr_name: '网络' },
    { id: '', name: '黑色', attr_id: '', attr_name: '颜色' }
  ],
  [
    { id: '', name: '联通', attr_id: '', attr_name: '运营商' },
    { id: '', name: '4G', attr_id: '', attr_name: '网络' },
    { id: '', name: '白色', attr_id: '', attr_name: '颜色' }
  ],
  [
    { id: '', name: '联通', attr_id: '', attr_name: '运营商' },
    { id: '', name: '5G', attr_id: '', attr_name: '网络' },
    { id: '', name: '黑色', attr_id: '', attr_name: '颜色' }
  ],
  [
    { id: '', name: '联通', attr_id: '', attr_name: '运营商' },
    { id: '', name: '5G', attr_id: '', attr_name: '网络' },
    { id: '', name: '白色', attr_id: '', attr_name: '颜色' }
  ]
]
  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
购物商城的Spu-Sku数据库设计主要是为了管理商品的库存和销售信息。Spu(Standard Product Unit)是商品的标准产品单位,通常指的是一组具有相同特征但可能有不同规格的商品,例如同一款衣服的不同颜色或尺码。Sku(Stock Keeping Unit)是商品的库存管理单位,是对Spu的具体细分,用于区分不同规格或属性的商品。 在数据库设计中,可以建立两个主要的表:Spu表和Sku表。Spu表用于存储商品的基本信息,包括商品的名称、描述、品牌、分类等。此外,可以为Spu表添加一些扩展字段,例如商品的图片、销售状态等。 Sku表用于存储商品的具体规格和库存信息,其中包括Spu的外键关联、商品的属性、规格、价格和库存数量等。通过外键关联,可以将Sku与其对应的Spu关联起来,实现Spu与Sku的多对一关系。同时,可以在Sku表中添加一些扩展字段,例如商品的条形码、上架时间等。 为了提高查询效率,可以在Sku表中添加索引,例如根据商品的价格、库存数量、销售状态等字段进行索引,以快速获取满足条件的商品信息。 此外,为了提高系统的可维护性和可扩展性,可以添加一些辅助表,例如属性表和属性值表,用于管理商品的属性信息。属性表用于存储商品的属性名称,属性值表用于存储属性的具体取值范围。 总之,购物商城的Spu-Sku数据库设计需要考虑Spu和Sku之间的关联关系,以及商品的基本信息和规格信息的存储和管理。通过合理的设计和优化索引,可以提高系统的查询性能和用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一米没有

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值