Filter array in objects array

Hello everyone, I have the following construct:

const allProducts = [
{
img:" xyz",
desc: "xyz",
categories:["Men", "Sportshoes"];
}
]

I want to get all products, where categories includes Men.
I tried: allProducts.filter((item)=>item.categories.includes("Men"))
also:

 allProducts.filter((item:any)=>{
        return item.categories[0] ==="Men";
    }).map(function (item:any) {
        return item[1];
      });

But both gives back an empty array. Thank you, for your help.

Well, if you get rid of the semi-colon in the following line, you will have an array containing a valid object.

Then, the following:

allProducts.filter((item)=>{
  return item.categories[0] ==="Men";
})

will return the following array:


[
 {
  img:" xyz",
  desc: "xyz",
  categories:["Men", "Sportshoes"]
  }
]

If you attempt to map over this filtered array with:

.map(function (item:any) {
  return item[1];
})

then you will get:

[ undefined ]

Why? Because there there is only a single element in the array at index 0. Trying to reference an element at index 1 returns undefined.

You just need to make the proper reference to the categories property in the following line:

return item[1];

Keep in mind, this array could have duplicates of the same product names if the category objects do not contain unique category/product names, ae current code does not attempt to remove them.

Thanks for your response. allProducts is an array of 21 objects like this:

  1. categories: [‘Men’ , ‘Sportshoes’]
  2. cloudinary_id: “l4x4u7w0bir6is4oo43a”
  3. colors: [‘black, white’]
  4. createdAt: “2022-12-27T09:46:40.973Z”
  5. currency: “€”
  6. desc: “Lorem Ipsum”
  7. image: “https://res.cloudinary.com/romandev/image/upload/v1672134400/l4x4u7w0bir6is4oo43a.jpg
  8. inStock: true
  9. price: “89”
  10. producer: “Adidas”
  11. sizes: [‘39, 42, 45’]
  12. title: “Test product 5”
  13. updatedAt: “2022-12-27T09:46:40.973Z”
  14. __v: 0
  15. _id: “63aabf005b63a9507cc2f4a3”
  16. [[Prototype]]: Object
    I tried now:
const productsMen = allProducts.filter((item:any)=>{
        return item.categories[0] ==="Men";
      })
      console.log(productsMen);

Gives back empty array. Then:

  const productsMen = allProducts.filter((item:any)=>{
        return item.categories[0] ==="Men";
      }).map(function (item:any) {
        return item[1];
      })

Gives back empty array. And this one is alo empty:

const productsMen = allProducts.filter((item:any)=>{
        return item.categories[0] ==="Men";
      }).map(function (item:any) {
        return item.categories[1];
      })

What can be the reaon for this behaviour? Thanks

Please post the actual array as code.

I get this Array from MongoDB. In code it must be:

const allProducts = [
{
 categories: [‘Men’ , ‘Sportshoes’],
 cloudinary_id: “l4x4u7w0bir6is4oo43a”,
colors: [‘black, white’],
createdAt: “2022-12-27T09:46:40.973Z”,
 currency: “€”,
desc: “Lorem Ipsum”,
image: “https://res.cloudinary.com/romandev/image/upload/v1672134400/l4x4u7w0bir6is4oo43a.jpg”,
 inStock: true,
price: “89”,
producer: “Adidas”,
sizes: [‘39, 42, 45’],
title: “Test product 5”,
updatedAt: “2022-12-27T09:46:40.973Z”,
__v: 0,
 _id: “63aabf005b63a9507cc2f4a3”,
}
]

When I do this, all twentyone Products are displayed correctly:

const productsChild = allProducts.filter((item:any)=>{
        return item;
      })
      console.log(productsChild);
  return (
    <Container>
      <ProductsWrapper>
        {productsChild.map((item:any)=>(
            <FieldWrapper key={item._id}>
                <ImgHolder>
                <img src={item.image} alt={item.categories} title={item.title}/>
                </ImgHolder>
                <DescHolder>
                    <h4>{item.title}</h4>
                    <h5>{item.categories}</h5>
                    <p>{item.desc}</p>
                    <p>{item.producer}</p>
                    <span>{item.price}{item.currency}</span>
                    <ColorHolder>
                    {item.colors.map((color:any)=>(
                        <div style={{backgroundColor:color}}></div>
                    ))}
                    </ColorHolder>
                </DescHolder>
            </FieldWrapper>
        ))}
      </ProductsWrapper>
    </Container>

The array code you posted has some formatting issues, but like I said before, if I fix the formatting issues and run:

const productsChild = allProducts.filter((item:any)=>{
        return item.categories[0] ==="Men";
      })
      console.log(productsChild);

I would see something like:

[
{
 categories: [‘Men’ , ‘Sportshoes’],
 cloudinary_id: “l4x4u7w0bir6is4oo43a”,
colors: [‘black, white’],
createdAt: “2022-12-27T09:46:40.973Z”,
 currency: “€”,
desc: “Lorem Ipsum”,
image: “https://res.cloudinary.com/romandev/image/upload/v1672134400/l4x4u7w0bir6is4oo43a.jpg”,
 inStock: true,
price: “89”,
producer: “Adidas”,
sizes: [‘39, 42, 45’],
title: “Test product 5”,
updatedAt: “2022-12-27T09:46:40.973Z”,
__v: 0,
 _id: “63aabf005b63a9507cc2f4a3”,
}
]

You only provided 1 object in the array above, so you will only get 1 object in the filtered array since the item.categories[0] is equal to "Men" for the 1 object and not an empty array.

Running the map as:

const productsMen = productsChild.map(function (item:any) {
        return item[1];
      })
console.log(productsMen);

would still result in:

[undefined]

because item is an object and not an array.

const productsChild = allProducts.filter((item:any)=>{
return item.categories[0] ===“Men”;
})
console.log(productsChild);
gives back in the console:
Array(0)length: 0[[Prototype]]: Array(0)
The code comes from mongoDB, so there can’t be any fomatting issues. I don’t know either, why it is empty. When I filter nothing, then it renders correctly all twentyone products. So the data is there. And there are several objects, who’s categories including “Men” as first element.

Do me a favor and add the following console.log statement above this line and copy/paste what it shows into a reply.

console.log(JSON.stringify(allProducts, null, 2));
1 Like

Yes, now I think it is clear. I send the data as FormData, so I have to stringify the arrays.

const onSubmit=(e:React.FormEvent<HTMLFormElement>)=>{
      e.preventDefault();
      const productData = new FormData();
      productData.append("title", formdata.title);
      productData.append("producer", formdata.producer);
      productData.append("categories", JSON.stringify(formdata.categories));
      productData.append("desc", formdata.desc);
      productData.append("price", formdata.price);
      productData.append("colors", JSON.stringify(formdata.colors));
      productData.append("sizes", JSON.stringify(formdata.sizes));
      productData.append("inStock", formdata.inStock);
      productData.append('image', fileData.image!)
      for(let value of productData){
        console.log(value);
      }
      dispatch(createProduct(productData));
    }

In node I parse them again:

 const newProducts = new Products({
            cloudinary_id: uploadResult.public_id,
            title: req.body.title,
            producer: req.body.producer,
            categories: JSON.parse(req.body.categories),
            desc: req.body.desc,
            price: req.body.price,
            currency:req.body.currency,
            colors:JSON.parse(req.body.colors),
            sizes: JSON.parse(req.body.sizes),
            inStock: req.body.inStock,
            image: uploadResult.secure_url,

        })

When I write in the input field categories: Men, Sportshoes, the entry in MongoDb is “Men, Sportshoes”. Thank you RandellDawson.