简体   繁体   中英

JS filter array by array within

I have an array as following

  [{
    "id": 68,
    "proffesional_photo": "",
    "top_image": "https://sampleimage.jpg",
    "ratings": "1",
    "price": 690,
    "description": null,
    "type": true,
    "promo": 0,
    "status": true,
    "item": {
      "Item_name": "Dark Chocolate Latte"
    },
    "restaurant_dish_menus": [
      {
        "id": 1,
        "res_dish_id": 1318,
        "menu_id": 4,
        "createdAt": "2018-11-13T04:28:17.000Z",
        "updatedAt": "2018-11-13T04:28:17.000Z"
      },
      {
        "id": 1,
        "res_dish_id": 1318,
        "menu_id": 3,
        "createdAt": "2018-11-13T04:28:17.000Z",
        "updatedAt": "2018-11-13T04:28:17.000Z"
      }
     ]
  },
  {
    "id": 69,
    "proffesional_photo": "",
    "top_image": "https://sampleimage2.jpg",
    "ratings": "1",
    "price": 700,
    "description": null,
    "type": true,
    "promo": 0,
    "status": true,
    "item": {
      "Item_name": "Latte"
    },
    "restaurant_dish_menus": [
      {
        "id": 1,
        "res_dish_id": 1318,
        "menu_id": 3,
        "createdAt": "2018-11-13T04:28:17.000Z",
        "updatedAt": "2018-11-13T04:28:17.000Z"
      }
     ]
  }
  ],

And when the user select a certain menu it needs to be filtered through it,

Each dish objects may have more than one menu_id,

i attempted using array.filter but i am having trouble figuring out how to filter from the Dish array through the sub array within.

the code i attempted ( filterBy = 4 )

let result = data.filter(function(row) {
  row.restaurant_dish_menus.filter(function(i) {
    return i.menu_id == filterBy;
  });
});

console.log(result) gives me an empty array.

if filterBy is = 4 the expected output is

{
    "id": 68,
    "proffesional_photo": "",
    "top_image": "https://sampleimage.jpg",
    "ratings": "1",
    "price": 690,
    "description": null,
    "type": true,
    "promo": 0,
    "status": true,
    "item": {
      "Item_name": "Dark Chocolate Latte"
    },
    "restaurant_dish_menus": [
      {
        "id": 1,
        "res_dish_id": 1318,
        "menu_id": 4,
        "createdAt": "2018-11-13T04:28:17.000Z",
        "updatedAt": "2018-11-13T04:28:17.000Z"
      },
      {
        "id": 1,
        "res_dish_id": 1318,
        "menu_id": 3,
        "createdAt": "2018-11-13T04:28:17.000Z",
        "updatedAt": "2018-11-13T04:28:17.000Z"
      }
     ]
  }

And if it filterBy is 3 then both objects should be the output

how about this

var data =   [{
    "id": 68,
    "proffesional_photo": "",
    "top_image": "https://sampleimage.jpg",
    "ratings": "1",
    "price": 690,
    "description": null,
    "type": true,
    "promo": 0,
    "status": true,
    "item": {
      "Item_name": "Dark Chocolate Latte"
    },
    "restaurant_dish_menus": [
      {
        "id": 1,
        "res_dish_id": 1318,
        "menu_id": 4,
        "createdAt": "2018-11-13T04:28:17.000Z",
        "updatedAt": "2018-11-13T04:28:17.000Z"
      },
      {
        "id": 1,
        "res_dish_id": 1318,
        "menu_id": 3,
        "createdAt": "2018-11-13T04:28:17.000Z",
        "updatedAt": "2018-11-13T04:28:17.000Z"
      }
     ]
  }];

  var result = data.filter(function(m) {
    return m.restaurant_dish_menus.some(function(d) {
      return d.menu_id === 4;
    });
  })

.filter expects the function passed to return a boolean. In your case, the function returns nothing (or undefined ) which is always falsy.

One option is to use .find in the nested filter, and return a boolean depending on whether the result is undefined .

Here's a snippet.

 let data = [{ "id": 68, "proffesional_photo": "", "top_image": "https://sampleimage.jpg", "ratings": "1", "price": 690, "description": null, "type": true, "promo": 0, "status": true, "item": { "Item_name": "Dark Chocolate Latte" }, "restaurant_dish_menus": [{ "id": 1, "res_dish_id": 1318, "menu_id": 4, "createdAt": "2018-11-13T04:28:17.000Z", "updatedAt": "2018-11-13T04:28:17.000Z" }, { "id": 1, "res_dish_id": 1318, "menu_id": 3, "createdAt": "2018-11-13T04:28:17.000Z", "updatedAt": "2018-11-13T04:28:17.000Z" } ] }, { "id": 69, "proffesional_photo": "", "top_image": "https://sampleimage.jpg", "ratings": "1", "price": 690, "description": null, "type": true, "promo": 0, "status": true, "item": { "Item_name": "Dark Chocolate Latte" }, "restaurant_dish_menus": [{ "id": 1, "res_dish_id": 1318, "menu_id": 6, "createdAt": "2018-11-13T04:28:17.000Z", "updatedAt": "2018-11-13T04:28:17.000Z" }, { "id": 1, "res_dish_id": 1318, "menu_id": 5, "createdAt": "2018-11-13T04:28:17.000Z", "updatedAt": "2018-11-13T04:28:17.000Z" } ] }, ] let filterBy = 4; let result = data.filter(function(row) { return row.restaurant_dish_menus.find(function(i) { return i.menu_id == filterBy; }) !== undefined; }); console.log(result); 

You can use "filter" as below

 var data = [{ "id": 68, "proffesional_photo": "", "top_image": "https://sampleimage.jpg", "ratings": "1", "price": 690, "description": null, "type": true, "promo": 0, "status": true, "item": { "Item_name": "Dark Chocolate Latte" }, "restaurant_dish_menus": [ { "id": 1, "res_dish_id": 1318, "menu_id": 4, "createdAt": "2018-11-13T04:28:17.000Z", "updatedAt": "2018-11-13T04:28:17.000Z" }, { "id": 1, "res_dish_id": 1318, "menu_id": 3, "createdAt": "2018-11-13T04:28:17.000Z", "updatedAt": "2018-11-13T04:28:17.000Z" } ] }, { "id": 69, "proffesional_photo": "", "top_image": "https://sampleimage2.jpg", "ratings": "1", "price": 700, "description": null, "type": true, "promo": 0, "status": true, "item": { "Item_name": "Latte" }, "restaurant_dish_menus": [ { "id": 1, "res_dish_id": 1318, "menu_id": 3, "createdAt": "2018-11-13T04:28:17.000Z", "updatedAt": "2018-11-13T04:28:17.000Z" } ] } ] function filterBy(f) { return data.filter(d => d.restaurant_dish_menus.some(({ menu_id }) => menu_id == f)) } console.log(filterBy(4)) console.log(filterBy(3)) 

You can also use grep function

var menus=  {
    "id": 68,
    "proffesional_photo": "",
    "top_image": "https://sampleimage.jpg",
    "ratings": "1",
    "price": 690,
    "description": null,
    "type": true,
    "promo": 0,
    "status": true,
    "item": {
      "Item_name": "Dark Chocolate Latte"
    },
    "restaurant_dish_menus": [
      {
        "id": 1,
        "res_dish_id": 1318,
        "menu_id": 4,
        "createdAt": "2018-11-13T04:28:17.000Z",
        "updatedAt": "2018-11-13T04:28:17.000Z"
      },
      {
        "id": 1,
        "res_dish_id": 1318,
        "menu_id": 3,
        "createdAt": "2018-11-13T04:28:17.000Z",
        "updatedAt": "2018-11-13T04:28:17.000Z"
      }
     ]
  };

var found_names = $.grep(menus.restaurant_dish_menus, function(v) {
    return v.menu_id ===4;
});

console.log(found_names);

http://jsfiddle.net/ejPV4/

Your question a bit unclear of final goal, but if you want to filter top level objects, ie if top level object has to be present if and only if it has dish with menu_id === filterBy , then:

let result = data.filter(row => {
  return row.restaurant_dish_menus.some(({menu_id}) => menu_id === filterBy);
});

Above will only filter your rows if restaurant_dish_menus has items with menu_id === filterBy . But restaurant_dish_menus , of such objects remain unfiltered.

Result:

[{
  "id": 68,
  // skipped
  "item": {
    "Item_name": "Dark Chocolate Latte"
  },
  "restaurant_dish_menus": [
    {
      "id": 1,
      "res_dish_id": 1318,
      "menu_id": 4,
      // skipped
    },
    {
      "id": 1,
      "res_dish_id": 1318,
      "menu_id": 3,
      // skipped
    }
  ]
}]

But if you want to filter top level and filter restaurant_dish_menus also, ie modify top level object, then:

let result = data.filter(row => {
  return row.restaurant_dish_menus.some(({menu_id}) => menu_id === filterBy);
}).map(row => {
  return {...row, restaurant_dish_menus: row.restaurant_dish_menus.filter(i => i.menu_id === filterBy)};
});

This will first filter the row objects which has menu_id === filterBy , and then also filter restaurant_dish_menus , to include only once menu_id === filterBy , effectively modifying the row object, ie map .

Result:

[{
  "id": 68,
  // skipped
  "item": {
    "Item_name": "Dark Chocolate Latte"
  },
  "restaurant_dish_menus": [
    {
      "id": 1,
      "res_dish_id": 1318,
      "menu_id": 4,
      // skipped
    }
  ]
}]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM