Javascript:将一系列产品选项组合分组并嵌套

时间:2020-03-21 18:15:21

标签: javascript arrays json

我有一组扁平的产品选项组合,例如“衬衫类型”,“颜色”和“尺寸”,我希望将它们转换为可嵌套的列表,以便更轻松地呈现给客户。

  • 嵌套的深度可以达到 级别(我的示例在下面的示例中显示了3个级别,但其他项目可能只有1或2个级别)。
  • 平面数组中的产品选项对象可以以某种方式出现 随机订购(即T恤,然后是运动衫,然后是T恤 再次)。
  • 并非每个值都存在于每个组中(即XL号可能仅显示 白色T恤)。
  • 此示例显示了衬衫,但选项类型可能完全相同 其他项目(例如,“ optionType1”可能是“框架尺寸”)不同

我需要转换的组合数据示例:

[
  {
    "skuid": "TSWHTM",
    "optionType1": "Shirt Type",
    "optionName1": "T-Shirt",
    "optionValue1": "TS",
    "optionType2": "Color",
    "optionName2": "White",
    "optionValue2": "WHT",
    "optionName3": "Size",
    "optionType3": "Medium",
    "optionValue3": "M"
  },
  {
    "skuid": "TSWHTL",
    "optionType1": "Shirt Type",
    "optionName1": "T-Shirt",
    "optionValue1": "TS",
    "optionType2": "Color",
    "optionName2": "White",
    "optionValue2": "WHT",
    "optionType3": "Size",
    "optionName3": "Large",
    "optionValue3": "L"
  },
  {
    "skuid": "TSBLKM",
    "optionType1": "Shirt Type",
    "optionName1": "T-Shirt",
    "optionValue1": "TS",
    "optionType2": "Color",
    "optionName2": "Black",
    "optionValue2": "BLK",
    "optionType3": "Size",
    "optionName3": "Medium",
    "optionValue3": "M"
  },
  {
    "skuid": "TSBLKL",
    "optionType1": "Shirt Type",
    "optionName1": "T-Shirt",
    "optionValue1": "TS",
    "optionType2": "Color",
    "optionName2": "Black",
    "optionValue2": "BLK",
    "optionType3": "Size",
    "optionName3": "Large",
    "optionValue3": "L"
  },
  {
    "skuid": "SSWHTM",
    "optionType1": "Shirt Type",
    "optionName1": "Sweatshirt",
    "optionValue1": "SS",
    "optionType2": "Color",
    "optionName2": "White",
    "optionValue2": "WHT",
    "optionType3": "Size",
    "optionName3": "Medium",
    "optionValue3": "M"
  },
  {
    "skuid": "SSWHTL",
    "optionType1": "Shirt Type",
    "optionName1": "Sweatshirt",
    "optionValue1": "SS",
    "optionType2": "Color",
    "optionName2": "White",
    "optionValue2": "WHT",
    "optionType3": "Size",
    "optionName3": "Large",
    "optionValue3": "L"
  },
  {
    "skuid": "SSBLKM",
    "optionType1": "Shirt Type",
    "optionName1": "Sweatshirt",
    "optionValue1": "SS",
    "optionType2": "Color",
    "optionName2": "Black",
    "optionValue2": "BLK",
    "optionType3": "Size",
    "optionName3": "Medium",
    "optionValue3": "M"
  },
  {
    "skuid": "TSWHTXL",             <-- CAN APPEAR OUT OF ORDER (UN-GROUPED WITH OTHER T-SHIRTS)
    "optionType1": "Shirt Type",
    "optionName1": "T-Shirt",
    "optionValue1": "TS",
    "optionType2": "Color",
    "optionName2": "White",
    "optionValue2": "WHT",
    "optionType3": "Size",
    "optionName3": "Extra Large",   <-- THIS SIZE ONLY AVAILABLE FOR T-SHIRT / WHITE
    "optionValue3": "XL"
  },  
  {
    "skuid": "SSBLKL",
    "optionType1": "Shirt Type",
    "optionName1": "Sweatshirt",
    "optionValue1": "SS",
    "optionType2": "Color",
    "optionName2": "Black",
    "optionValue2": "BLK",
    "optionType3": "Size",
    "optionName3": "Large",
    "optionValue3": "L"
  }
]

下面是将其转换为以下内容的示例:

{
  "options": [
    {
      "optionType1": "Shirt Type",
      "optionName1": "T-Shirt",
      "optionValue1": "TS",
      "options": [
        {
          "optionType2": "Color",
          "optionName2": "White",
          "optionValue2": "WHT",
          "options": [
            {
              "optionType3": "Size",
              "optionName3": "Medium",
              "optionValue3": "M",
              "skuid": "TSWHTM"
            },
            {
              "optionType3": "Size",
              "optionName3": "Large",
              "optionValue3": "L",
              "skuid": "TSWHTL"
            },
            {
              "optionType3": "Size",
              "optionName3": "Extra Large",
              "optionValue3": "XL",
              "skuid": "TSWHTXL"
            }
          ]
        },
        {
          "optionType2": "Color",
          "optionName2": "Black",
          "optionValue2": "BLK",
          "options": [
            {
              "optionType3": "Size",
              "optionName3": "Medium",
              "optionValue3": "M",
              "skuid": "TSWHTM"
            },
            {
              "optionType3": "Size",
              "optionName3": "Large",
              "optionValue3": "L",
              "skuid": "TSWHTL"
            }
          ]
        }
      ]
    },
    {
      "optionType1": "Shirt Type",
      "optionName1": "Sweatshirt",
      "optionValue1": "SS",
      "options": [
        {
          "optionType2": "Color",
          "optionName2": "White",
          "optionValue2": "WHT",
          "options": [
            {
              "optionType3": "Size",
              "optionName3": "Medium",
              "optionValue3": "M",
              "skuid": "SSWHTM"
            },
            {
              "optionType3": "Size",
              "optionName3": "Large",
              "optionValue3": "L",
              "skuid": "SSWHTL"
            }
          ]
        },
        {
          "optionType2": "Color",
          "optionName2": "Black",
          "optionValue2": "BLK",
          "options": [
            {
              "optionType3": "Size",
              "optionName3": "Medium",
              "optionValue3": "M",
              "skuid": "SSWHTM"
            },
            {
              "optionType3": "Size",
              "optionName3": "Large",
              "optionValue3": "L",
              "skuid": "SSWHTL"
            }
          ]
        }
      ]
    }
  ]
}

然后,我可以在UI中显示“衬衫类型”,“颜色”和“尺寸”菜单,并在做出选择时更新每个菜单(基于可用性)。

这是我想出的模型,尽管我没有结婚,但如果有人有更好的建模想法,那是我想起的模型。我开始编写进行转换的代码,但很快就变成了意大利面,所以我想在这里问。

1 个答案:

答案 0 :(得分:1)

您可以迭代数据并将对象用作结果集。

在迭代过程中,循环一个用于选择键的计数器,并检查该键是否存在于实际对象中。如果未创建,则创建一个新对象并将其用于下一个计数器循环。

结果,您将获得带有嵌套数组的对象数组。

var data = [{ skuid: "TSWHTM", optionType1: "Shirt Type", optionName1: "T-Shirt", optionValue1: "TS", optionType2: "Color", optionName2: "White", optionValue2: "WHT", optionName3: "Size", optionType3: "Medium", optionValue3: "M" }, { skuid: "TSWHTL", optionType1: "Shirt Type", optionName1: "T-Shirt", optionValue1: "TS", optionType2: "Color", optionName2: "White", optionValue2: "WHT", optionType3: "Size", optionName3: "Large", optionValue3: "L" }, { skuid: "TSBLKM", optionType1: "Shirt Type", optionName1: "T-Shirt", optionValue1: "TS", optionType2: "Color", optionName2: "Black", optionValue2: "BLK", optionType3: "Size", optionName3: "Medium", optionValue3: "M" }, { skuid: "TSBLKL", optionType1: "Shirt Type", optionName1: "T-Shirt", optionValue1: "TS", optionType2: "Color", optionName2: "Black", optionValue2: "BLK", optionType3: "Size", optionName3: "Large", optionValue3: "L" }, { skuid: "SSWHTM", optionType1: "Shirt Type", optionName1: "Sweatshirt", optionValue1: "SS", optionType2: "Color", optionName2: "White", optionValue2: "WHT", optionType3: "Size", optionName3: "Medium", optionValue3: "M" }, { skuid: "SSWHTL", optionType1: "Shirt Type", optionName1: "Sweatshirt", optionValue1: "SS", optionType2: "Color", optionName2: "White", optionValue2: "WHT", optionType3: "Size", optionName3: "Large", optionValue3: "L" }, { skuid: "SSBLKM", optionType1: "Shirt Type", optionName1: "Sweatshirt", optionValue1: "SS", optionType2: "Color", optionName2: "Black", optionValue2: "BLK", optionType3: "Size", optionName3: "Medium", optionValue3: "M" }, { skuid: "TSWHTXL", optionType1: "Shirt Type", optionName1: "T-Shirt", optionValue1: "TS", optionType2: "Color", optionName2: "White", optionValue2: "WHT", optionType3: "Size", optionName3: "Extra Large", optionValue3: "XL" }, { skuid: "SSBLKL", optionType1: "Shirt Type", optionName1: "Sweatshirt", optionValue1: "SS", optionType2: "Color", optionName2: "Black", optionValue2: "BLK", optionType3: "Size", optionName3: "Large", optionValue3: "L" }],
    keys = ['optionType', 'optionName', 'optionValue'],
    result = data
        .reduce((r, o) => {
            var t = r;

            for (let i = 1, key = 'optionValue' + i; key in o; key = 'optionValue' + ++i) {
                let item = (t.option = t.option || []).find(q => q[key] === o[key]);
                if (!item) t.option.push(item = Object.fromEntries(keys.map(k => [k + i, o[k + i]])));
                t = item;
            }
            t.skuid = o.skuid;

            return r;
        }, { option: [] })
        .option;    
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }