1

I have the following JSON structure:

{
  "id": 123,
  "shops": [
    {
      "shopId": 456,
      "products": [
        {
          "productId": 10001,
          "name": "abc",
          "state": "active"
        },
        {
          "productId": 10002,
          "name": "def",
          "state": "expired"
        }
      ]
    },
    {
      "shopId": 789,
      "products": [
        {
          "productId": 20001,
          "name": "qrt",
          "state": "expired"
        },
        {
          "productId": 20002,
          "name": "jbf",
          "state": "active"
        }
      ]
    }
  ]
}

I want to remove all products from each shop where the product does not have certain properties.

If I covert it to a flat map then I can do it fine, but then I lose the outer object as I just have an array with all the products that haven't been removed in.

_(shopJson.shops).map('products').flatten().map(x => {if(x.state === 'active'){return x}}).compact().value()

I tried the following but just end up with an empty array:

_(shopJson.shops).map('products').filter(x => x.state === 'active').value()

I also tried using _.reduce() and _.transform() but can't get it to work

The final JSON should look like:

{
  "id": 123,
  "shops": [
    {
      "shopId": 456,
      "products": [
        {
          "productId": 10001,
          "name": "abc",
          "state": "active"
        }
      ]
    },
    {
      "shopId": 789,
      "products": [
        {
          "productId": 20002,
          "name": "jbf",
          "state": "active"
        }
      ]
    }
  ]
}

1 Answer 1

3

You don't really need lodash for this. You can just use Array.prototype.map and Array.protype.filter (and also some spread syntax to shallow merge object properties):

const data = {id:123,shops:[{shopId:456,products:[{productId:10001,name:"abc",state:"active"},{productId:10002,name:"def",state:"expired"}]},{shopId:789,products:[{productId:20001,name:"qrt",state:"expired"},{productId:20002,name:"jbf",state:"active"}]}]};

const result = {
  ...data,
  shops: data.shops.map((shop) => ({
    ...shop,
    products: shop.products.filter((product) => product.state === 'active'),
  })),
};

console.log(result);

EDIT: As @Deykun pointed out, if you want to ignore shops that don't have any active products, you can filter shops out using Array.prototype.some in a filter:

const data = {id:123,shops:[{shopId:456,products:[{productId:10001,name:"abc",state:"active"},{productId:10002,name:"def",state:"expired"}]},{shopId:789,products:[{productId:20001,name:"qrt",state:"expired"},{productId:20002,name:"jbf",state:"expired"}]}]};
    
const result = {
  ...data,
  shops: data.shops
    .filter((shop) => shop.products.some((product) => product.state === 'active'))
    .map((shop) => ({
      ...shop,
      products: shop.products.filter((product) => product.state === 'active')
  }))
};

console.log(result);

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

2 Comments

I agree that lodash is not needed here, but I would consider adding shops: data.shops.filter( s => s.products.some(p => p.state === 'active') ).map( ... to ignore shops without active products.
@Deykun Good point. Edited my answer to mention this. Thanks! :)

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.