【问题标题】:Filtering nested JSON array in javascript and returning inner array which matches a criteria在javascript中过滤嵌套的JSON数组并返回匹配条件的内部数组
【发布时间】:2019-06-27 04:49:23
【问题描述】:

我有一个这样的 json 对象:

{
  "products": [
    {
      "ID": "001",
      "Attributes": [
        {
          "value": "BESTSELLERS",
          "identifier": "BEST_SELLER"
        },
        {
          "value": "Color",
          "identifier": "Green"
        },
        {
          "value": "Size",
          "identifier": "L"
        }
      ],
      "SKUs": [
        {
          "ID": "001_1",
          "Attributes": [
            {
              "value": "BESTSELLERS",
              "identifier": "BEST_SELLER"
            },
            {
              "value": "Color",
              "identifier": "Green"
            },
            {
              "value": "Size",
              "identifier": "L"
            }
          ]
        },
        {
          "ID": "001_2",
          "Attributes": [
            {
              "value": "BESTSELLERS",
              "identifier": "BEST_SELLER"
            },
            {
              "value": "Color",
              "identifier": "Yellow"
            },
            {
              "value": "Size",
              "identifier": "M"
            }
          ]
        }
      ]
    },
    {
      "ID": "002",
      "Attributes": [
        {
          "value": "BESTSELLERS",
          "identifier": "BEST_SELLER"
        },
        {
          "value": "Size",
          "identifier": "L"
        }
      ],
      "SKUs": [
        {
          "ID": "002_1",
          "Attributes": [
            {
              "value": "BESTSELLERS",
              "identifier": "BEST_SELLER"
            },
            {
              "value": "Color",
              "identifier": "Black"
            },
            {
              "value": "Size",
              "identifier": "L"
            }
          ]
        },
        {
          "ID": "002_2",
          "Attributes": [
            {
              "value": "BESTSELLERS",
              "identifier": "BEST_SELLER"
            },
            {
              "value": "Color",
              "identifier": "Grey"
            }
          ]
        }
      ]
    },
    {
      "ID": "003",
      "Attributes": [
        {
          "value": "BESTSELLERS",
          "identifier": "BEST_SELLER"
        },
        {
          "value": "Color",
          "identifier": "Blue"
        }
      ],
      "SKUs": []
    }
  ]
}')

如您所见,products 是一个数组,其中包含另一个数组 SKUs,其中包含另一个数组 Attributes

我想获取所有具有 BOTH 属性的 SKU - SizeColor

所以,它应该返回

SKUs 001_1, 001_2 and 002_1

所以,我写了以下代码:

var obj = JSON.parse('<MyAboveJSONObjectHere>');
obj.products.filter( p => p.SKUs.filter(sku => sku.Attributes.filter(att => 
att.identifier === 'Color' && att.identifier === 'Size')))

但这会返回JSON 内的所有3 产品对象。

你能告诉我的代码表达式有什么问题吗?

【问题讨论】:

  • att.identifier === 'Color' &amp;&amp; att.identifier === 'Size' 一个属性不能同时保存两个不同的值
  • 试试att.identifier === 'Color' || att.identifier === 'Size'
  • 因为你的结构看起来很标准,你可以访问12索引来检查color and size是否可用
  • 不就是 att.value=='Color' && att.value=='Size' 吗?

标签: javascript arrays json filter


【解决方案1】:

reduce":

data.products.reduce((p, c) => (
  (c.SKUs = c.SKUs.filter(
    sku =>
      sku.Attributes.some(att => att.value === "Color") &&
      sku.Attributes.some(att => att.value === "Size")
  )).length && p.push(c), p ),[]
);

data = {
  products: [
    {
      ID: "001",
      Attributes: [
        {
          value: "BESTSELLERS",
          identifier: "BEST_SELLER"
        },
        {
          value: "Color",
          identifier: "Green"
        },
        {
          value: "Size",
          identifier: "L"
        }
      ],
      SKUs: [
        {
          ID: "001_1",
          Attributes: [
            {
              value: "BESTSELLERS",
              identifier: "BEST_SELLER"
            },
            {
              value: "Color",
              identifier: "Green"
            },
            {
              value: "Size",
              identifier: "L"
            }
          ]
        },
        {
          ID: "001_2",
          Attributes: [
            {
              value: "BESTSELLERS",
              identifier: "BEST_SELLER"
            },
            {
              value: "Color",
              identifier: "Yellow"
            },
            {
              value: "Size",
              identifier: "M"
            }
          ]
        }
      ]
    },
    {
      ID: "002",
      Attributes: [
        {
          value: "BESTSELLERS",
          identifier: "BEST_SELLER"
        },
        {
          value: "Size",
          identifier: "L"
        }
      ],
      SKUs: [
        {
          ID: "002_1",
          Attributes: [
            {
              value: "BESTSELLERS",
              identifier: "BEST_SELLER"
            },
            {
              value: "Color",
              identifier: "Black"
            },
            {
              value: "Size",
              identifier: "L"
            }
          ]
        },
        {
          ID: "002_2",
          Attributes: [
            {
              value: "BESTSELLERS",
              identifier: "BEST_SELLER"
            },
            {
              value: "Color",
              identifier: "Grey"
            }
          ]
        }
      ]
    },
    {
      ID: "003",
      Attributes: [
        {
          value: "BESTSELLERS",
          identifier: "BEST_SELLER"
        },
        {
          value: "Color",
          identifier: "Blue"
        }
      ],
      SKUs: []
    }
  ]
};

console.log(data.products.reduce((p, c) => (
    (c.SKUs = c.SKUs.filter(
      sku =>
        sku.Attributes.some(att => att.value === "Color") &&
        sku.Attributes.some(att => att.value === "Size")
    )).length && p.push(c), p ),[]
));

【讨论】:

    【解决方案2】:

    如果我理解正确,您希望从提供的 products 数组中获取 SKU ID 值列表,其中这些 SKU 项目具有 Attribute 子数组,其中包含 "Color""Size" 的值.

    这可以通过reduce() 实现,其中减少回调根据属性标准过滤 SKU 项目。然后将任何过滤的 SKU 项目映射到它们的 ID 字段,并收集(​​通过 concat())到生成的 output 数组中,如下所示:

    const obj={"products":[{"ID":"001","Attributes":[{"value":"BESTSELLERS","identifier":"BEST_SELLER"},{"value":"Color","identifier":"Green"},{"value":"Size","identifier":"L"}],"SKUs":[{"ID":"001_1","Attributes":[{"value":"BESTSELLERS","identifier":"BEST_SELLER"},{"value":"Color","identifier":"Green"},{"value":"Size","identifier":"L"}]},{"ID":"001_2","Attributes":[{"value":"BESTSELLERS","identifier":"BEST_SELLER"},{"value":"Color","identifier":"Yellow"},{"value":"Size","identifier":"M"}]}]},{"ID":"002","Attributes":[{"value":"BESTSELLERS","identifier":"BEST_SELLER"},{"value":"Size","identifier":"L"}],"SKUs":[{"ID":"002_1","Attributes":[{"value":"BESTSELLERS","identifier":"BEST_SELLER"},{"value":"Color","identifier":"Black"},{"value":"Size","identifier":"L"}]},{"ID":"002_2","Attributes":[{"value":"BESTSELLERS","identifier":"BEST_SELLER"},{"value":"Color","identifier":"Grey"}]}]},{"ID":"003","Attributes":[{"value":"BESTSELLERS","identifier":"BEST_SELLER"},{"value":"Color","identifier":"Blue"}],"SKUs":[]}]};
    
    /* Filter each product by the required SKU/attribute criteria */
    const result = obj.products.reduce((output, product) => {
    
      /* Determine if this products SKUs have contain requied attribute values */
      return output.concat(product.SKUs.filter((sku) => {
    
        const attributes = sku.Attributes;
    
        /* Search the attributes of this sku, looking for any with values that
        are color or size */
        const hasColor = attributes.some((attribute) => attribute.value === 'Color');
        const hasSize = attributes.some((attribute) => attribute.value === 'Size');
    
        /* If both attribute values found then this sku matches required criteria */
        return hasColor && hasSize;
      })
      /* Map any filtered sku to it's ID and concat the result to output */
      .map(sku => sku.ID));
    
    }, []);
    
    console.log(result);

    【讨论】:

      【解决方案3】:
      obj.products.map( p => {
             return p.SKUs.map(sku => {
          return sku.Attributes.filter(att => att.identifier === 'Color' && att.identifier === 'Size')}}
      

      试试这个,基本上你需要先map通过数组并且只在最后一个filter

      【讨论】:

        【解决方案4】:

        我相信您必须检查值而不是标识符。根据您的对象,您正在检查的值位于属性对象的值键中。您还应该检查内部过滤器的返回值的数组长度。如果在条件中传递一个空数组,仍将被视为 true,这就是您的过滤器始终返回对象的所有内容的原因。所以过滤器应该看起来像这样。

        obj.products.filter( p => p.SKUs.filter( att => att.Attributes.filter(inner => inner.value == 'Color' || inner.value == 'Size').length > 0 ? true : false).length > 0 ? true : false)
        

        【讨论】:

          猜你喜欢
          • 2021-11-21
          • 1970-01-01
          • 1970-01-01
          • 2022-01-25
          • 2022-01-26
          • 2021-12-29
          • 2013-11-28
          • 2021-12-13
          • 2022-08-17
          相关资源
          最近更新 更多