Фильтрация вложенного массива JSON в javascript и возврат внутреннего массива, который соответствует критериям - PullRequest
0 голосов
/ 27 июня 2019

У меня есть объект 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.

Я хочу получить все те SKU, которые имеют ОБА атрибутов - Size и Color для них.

Итак, он должен вернуть

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')))

Но это возвращает все 3 объекты продукта внутри JSON.

Подскажите, пожалуйста, что не так с моим кодовым выражением?

Ответы [ 4 ]

1 голос
/ 27 июня 2019

Если я правильно понимаю, вы хотите получить список значений SKU ID из поставляемого массива products, в котором эти элементы 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);
1 голос
/ 27 июня 2019

С 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 ),[]
));
0 голосов
/ 27 июня 2019

Я считаю, что вы должны проверить значение вместо идентификатора.В зависимости от вашего объекта проверяемое значение находится в ключе значения объекта атрибута.Вы также должны проверить длину массива возвращаемого значения внутренних фильтров.Пустой массив, если он передан в условии, все равно будет считаться истинным, поэтому ваш фильтр всегда возвращает все содержимое вашего объекта.поэтому фильтр должен выглядеть примерно так.

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)
0 голосов
/ 27 июня 2019
obj.products.map( p => {
       return p.SKUs.map(sku => {
    return sku.Attributes.filter(att => att.identifier === 'Color' && att.identifier === 'Size')}}

Попробуйте это, в основном вам нужно сначала map через массивы и только на последнем filter

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...