0

I have these data structure

products:[
      {
        products_number: 14,
        products_ID: 'lvs_jeans-man',
        products_seller: 'a',
        products_SKU: [
          {
            productSKU_ID: 'nfl_lvs_jeans-man_xl_bl-stripe',
            productSKU_size: 'XL',
            productSKU_color: 'Blue_White'
          },
          {
            productSKU_ID: 'nfl_lvs_jeans-man_xl_bk',
            productSKU_size: 'XL',
            productSKU_color: 'Black'
          }
        ]
      },
      {
      products_number: 15,
      products_ID: 'lvs_jeans-man',
      products_seller: 'b',
      products_SKU: [
        {
          productSKU_ID: 'nfl_lvs_jeans-man_xl_bk',
          productSKU_size: 'XL',
          productSKU_color: 'Black'
        }
      ]
    },
    {
      products_number: 16,
      products_ID: 'lvs_jeans-man',
      products_seller: 'c',
      products_SKU: [
        {
          productSKU_ID: 'nfl_lvs_jeans-man_xl_gy',
          productSKU_size: 'XL',
          productSKU_color: 'Grey',

        }
      ]
    }
  ]

The constant

  var id = 'lvs_jeans-man'
  var size = 'XL'
  var color = 'Black'

How do i filter items that met these condition

products_ID == id
productSKU_color == color
productSKU_size == size

The needed output is

  [{
    products_number: 14,
    products_ID: 'lvs_jeans-man',
    products_seller: 'a',
    productSKU_ID: 'nfl_lvs_jeans-man_xl_bk',
  },
  {
    products_number: 15,
    products_ID: 'lvs_jeans-man',
    products_seller: 'b',
    productSKU_ID: 'nfl_lvs_jeans-man_xl_bk',
  }]

What i have tried is filter the products_ID first then filter the color and size so i can get the productSKU_ID inside and then just play around with array push, but it return Cannot read property 'filter' of undefined"

var temp1 =  this.products.filter((product => product.products_ID === this.id).products_SKU.filter(sku => (sku.productSKU_color === this.color && sku.productSKU_size === this.size)))

How to achieve the needed output?

4 Answers 4

1

The function filter is not suitable because you need to build a custom output with data from the array .products_SKU.

Use this alternative using the functions reduce and find.

var data = {  products: [{      products_number: 14,      products_ID: 'lvs_jeans-man',      products_seller: 'a',      products_SKU: [{          productSKU_ID: 'nfl_lvs_jeans-man_xl_bl-stripe',          productSKU_size: 'XL',          productSKU_color: 'Blue_White'        },        {          productSKU_ID: 'nfl_lvs_jeans-man_xl_bk',          productSKU_size: 'XL',          productSKU_color: 'Black'        }      ]    },    {      products_number: 15,      products_ID: 'lvs_jeans-man',      products_seller: 'b',      products_SKU: [{        productSKU_ID: 'nfl_lvs_jeans-man_xl_bk',        productSKU_size: 'XL',        productSKU_color: 'Black'      }]    },    {      products_number: 16,      products_ID: 'lvs_jeans-man',      products_seller: 'c',      products_SKU: [{        productSKU_ID: 'nfl_lvs_jeans-man_xl_gy',        productSKU_size: 'XL',        productSKU_color: 'Grey',      }]    }  ]};

var id = 'lvs_jeans-man'
var size = 'XL'
var color = 'Black'

var result = data.products.reduce((a, p) => {
  var found;
  if (p.products_ID == id && (found = p.products_SKU.find(s => s.productSKU_size === size && s.productSKU_color === color))) {

    a.push({
      products_number: p.products_number,
      products_ID: p.products_ID,
      products_seller: p.products_seller,
      productSKU_ID: found.productSKU_ID
    });
  }

  return a;
}, []);

console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you. It works :) But if there are 1000+ products, is the better approach should match the products_id first then the size and color or still the same?
@nfl-x yes, you need to check the Id first.
0

It's too complicated for filter alone, you'll have to use more array methods, including reduce and find:

const input = {
  products: [{
      products_number: 14,
      products_ID: 'lvs_jeans-man',
      products_seller: 'a',
      products_SKU: [{
          productSKU_ID: 'nfl_lvs_jeans-man_xl_bl-stripe',
          productSKU_size: 'XL',
          productSKU_color: 'Blue_White'
        },
        {
          productSKU_ID: 'nfl_lvs_jeans-man_xl_bk',
          productSKU_size: 'XL',
          productSKU_color: 'Black'
        }
      ]
    },
    {
      products_number: 15,
      products_ID: 'lvs_jeans-man',
      products_seller: 'b',
      products_SKU: [{
        productSKU_ID: 'nfl_lvs_jeans-man_xl_bk',
        productSKU_size: 'XL',
        productSKU_color: 'Black'
      }]
    },
    {
      products_number: 16,
      products_ID: 'lvs_jeans-man',
      products_seller: 'c',
      products_SKU: [{
        productSKU_ID: 'nfl_lvs_jeans-man_xl_gy',
        productSKU_size: 'XL',
        productSKU_color: 'Grey',

      }]
    }
  ]
};

const matchingProducts = input.products.filter(({ products_ID }) => products_ID === 'lvs_jeans-man');
const output = matchingProducts.reduce((matches, product) => {
  const foundSizeObj = product.products_SKU.find(({ productSKU_color, productSKU_size }) => {
    return productSKU_size === 'XL' && productSKU_color === 'Black';
  });
  if (!foundSizeObj) return matches;
  const match = {...product};
  delete match.products_SKU;
  match.productSKU_ID = foundSizeObj.productSKU_ID;
  matches.push(match);
  return matches;
}, []);
console.log(output);

1 Comment

Thank you. This works too and this filtering the same products_ID first which might better if i have 1000+ products that i actually needed but i don't describe in my question. So, i'm sorry if i accept @Ete answer.
0

You can filter by id first and then map products with first found productSKU, take out the products with undefined productSKU and map that to a result type:

const products = [
  {
    products_number: 14,
    products_ID: 'lvs_jeans-man',
    products_seller: 'a',
    products_SKU: [
      {
        productSKU_ID: 'nfl_lvs_jeans-man_xl_bl-stripe',
        productSKU_size: 'XL',
        productSKU_color: 'Blue_White'
      },
      {
        productSKU_ID: 'nfl_lvs_jeans-man_xl_bk',
        productSKU_size: 'XL',
        productSKU_color: 'Black'
      }
    ]
  },
  {
    products_number: 15,
    products_ID: 'lvs_jeans-man',
    products_seller: 'b',
    products_SKU: [
      {
        productSKU_ID: 'nfl_lvs_jeans-man_xl_bk',
        productSKU_size: 'XL',
        productSKU_color: 'Black'
      }
    ]
  },
  {
    products_number: 16,
    products_ID: 'lvs_jeans-man',
    products_seller: 'c',
    products_SKU: [
      {
        productSKU_ID: 'nfl_lvs_jeans-man_xl_gy',
        productSKU_size: 'XL',
        productSKU_color: 'Grey',

      }
    ]
  }
];

const filterProducts = products => (id,size,color) =>
  products.filter(//filter by id first
    product=>product.products_ID===id
  )
  .map(//map to products with filtered productSKU
    product=>({
      ...product,
      products_SKU: product.products_SKU.find(
        info=>
          info.productSKU_size===size &&
          info.productSKU_color===color
      )
    })
  )
  .filter(//take out empty products_SKU
    product=>
      product.products_SKU!==undefined
  );

const mapToResult = product => ({
  products_number: product.products_number,
  products_ID: product.products_ID,
  products_seller: product.products_seller,
  productSKU_ID: product.products_SKU.productSKU_ID
});

console.log(
  filterProducts(products)("lvs_jeans-man","XL","Black")
  .map(mapToResult)
);

Update

const myFunction = arg => otherArg => 22

Is a function that returns a function, without the arrow syntax it would look like this:

function myFunction(arg){
  return function(otherArg){return 22; }
}

In the filterProducts you can use it to have filter linked to a set of products, for example:

const filterPants = filterProducts(products.filter(pantsOnly))

The optimized answer from Ele would look like this:

var result = data.products.reduce((a, p) => {
  if (p.products_ID == id) {
    //only check found if id matches
    const found = p.products_SKU.find(
      s => s.productSKU_size === size && s.productSKU_color === color
    );
    if(!found){
      return a;//early return
    }
    a.push({
      products_number: p.products_number,
      products_ID: p.products_ID,
      products_seller: p.products_seller,
      productSKU_ID: found.productSKU_ID
    })
  }

  return a;
}, []);

3 Comments

Thank you. What does products => (id,size,color) => mean and the equivalent of that in ecma5 ?
@nfl-x It's a function that takes an argument and returns a function, I updated the answer.
Oh i see. It still look complicated though for me. :D But thanks for the optimized answer.
0
const finalProducts = this.products.reduce((final, product) =>  {
  if (product.id === this.id || !this.id) {
    return[...final, ...product.products_SKU.reduce((acc, p) => {
      if (p.productSKU_size === this.size && p.productSKU_color === this.color) {
        return [...acc, {
          products_number: product.products_number,
          products_ID: product.products_ID,
          products_seller: product.products_seller,
          productSKU_ID: p.productSKU_ID
        }];
      }
      return acc;
    }, [])];
  }
  return final;
}, []);

finalProducs will be your expected output.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.