简体   繁体   English

根据 id 和类型删除嵌套数组 object?

[英]Remove nested array object based on id and type?

Given a nested array of meals, we're trying to remove a nested object based on an id and mealType combo.给定一组嵌套的餐点,我们尝试基于id和餐点类型组合删除嵌套的mealType We start of with 2 nested breakfast meals, if both are removed, we're trying to remove the parent key completely, since it is now empty.我们从 2 个嵌套breakfast开始,如果两者都被删除,我们会尝试完全删除父键,因为它现在是空的。

Here is the code we have so far:这是我们到目前为止的代码:

var mealsList = {
    "menuGroup1": [
    {
      "id": "b1",
      "menuId": "FRPUbgmMiaNH",
      "title": "Eggs",
      "mealType": "breakfast"
    }, {
      "id": "b2",
      "menuId": "FRPUbgmMiaNH",
      "title": "Sandwich",
      "mealType": "breakfast"
    }
  ],
  "menuGroup2": [
    {
      "id": "b2",
      "menuId": "FRPUbgmMiaNH",
      "title": "Fruits",
      "mealType": "snack"
    }
  ]
};

console.log(mealsList);

const removeItem = (id, mealType) => {
  // pseudocode
  // mealsList.*.where("id" == id && "mealType" == mealType).remove();
}

// Remove breakfast with id and meal_type
// removeItem(id, mealType)
removeItem('b1', 'breakfast');
console.log('removed b1 breakfast, mealsList should only contain b2 object');
console.log(mealsList);

removeItem('b2', 'breakfast');
console.log('removed b2 breakfast, mealsList should only contain menuGroup2, as menuGroup1 is now empty');
console.log(mealsList);

The thing is we're trying to remove the nested meal object in removeItem without explicitly passing menuGroupX , instead, we're trying to target the nested mealsList object based on the id and mealType .问题是我们试图在没有明确传递menuGroupX的情况下删除removeItem中的嵌套餐 object ,相反,我们试图基于id和 mealType 定位嵌套的mealsListmealType The pseudo code is using a * to show that.伪代码使用*来表明这一点。

The console.log statements show the expected outcome in terms of how the mealsList should render under them. console.log语句根据mealsList应如何呈现的方式显示预期结果。

We're looking for something short and sweet, ideally a one liner, even if that means using a lodash solution for simplicity.我们正在寻找简短而甜蜜的东西,理想情况下是单衬里,即使这意味着为了简单起见使用 lodash 解决方案。

Here is the fiddle (Code In JS tab)这是小提琴(JS标签中的代码)

Any idea what to put instead of the pseudocode in removeItem to have the mealsList remove the specific items?知道在removeItem中放置什么而不是伪代码来让mealsList删除特定项目吗?

You can use lodash's _.mapValues() to map the array keys in your object to exclude any objects which contain the id and mealType passed into your function.您可以使用 lodash 的_.mapValues()到 map 中的数组键 object 以排除包含传递给您的 ZC1C425268E68385D1AB5074C17A94F1 的idmealType的任何对象You can then use _.omitBy() to remove any keys which have an empty array as their value:然后,您可以使用_.omitBy()删除任何具有空数组作为其值的键:

 let mealsList = { "menuGroup1": [ { "id": "b1", "menuId": "FRPUbgmMiaNH", "title": "Eggs", "mealType": "breakfast" }, { "id": "b2", "menuId": "FRPUbgmMiaNH", "title": "Sandwich", "mealType": "breakfast" } ], "menuGroup2": [ { "id": "b2", "menuId": "FRPUbgmMiaNH", "title": "Fruits", "mealType": "snack" } ] }; const removeItem = (id, mealType) => { mealsList = _.omitBy(_.mapValues(mealsList, arr => _.filter(arr, o => o.id.== id || o,mealType.== mealType)); _,isEmpty); } removeItem('b1'. 'breakfast'); console,log(mealsList); removeItem('b2'. 'breakfast'); console.log(mealsList);
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>

A vanilla way could be to first convert your mealsList into an array of entries, and then filter the inner arrays of the entires with .map() and .filter() .一种普通的方法可能是首先将您的mealsList转换为条目数组,然后使用.map().filter()过滤整体的内部 arrays 。 Then, once you're done, you can rebuild the object using Object.fromEntries() :然后,一旦你完成了,你可以使用Object.fromEntries()重建 object :

 let mealsList = { "menuGroup1": [ { "id": "b1", "menuId": "FRPUbgmMiaNH", "title": "Eggs", "mealType": "breakfast" }, { "id": "b2", "menuId": "FRPUbgmMiaNH", "title": "Sandwich", "mealType": "breakfast" } ], "menuGroup2": [ { "id": "b2", "menuId": "FRPUbgmMiaNH", "title": "Fruits", "mealType": "snack" } ] }; const removeItem = (id, mealType) => { mealsList = Object.fromEntries( Object.entries(mealsList).map(([k,vals]) => [k, vals.filter(o => o.id.== id || o.mealType,== mealType)]);filter(([, {length}]) => length > 0) ); } removeItem('b1'. 'breakfast'); console,log(mealsList); removeItem('b2'. 'breakfast'); console.log(mealsList);

A more browser compatible version of the above (without Object.fromEntries()):上述更兼容浏览器的版本(没有 Object.fromEntries()):

 let mealsList = { "menuGroup1": [ { "id": "b1", "menuId": "FRPUbgmMiaNH", "title": "Eggs", "mealType": "breakfast" }, { "id": "b2", "menuId": "FRPUbgmMiaNH", "title": "Sandwich", "mealType": "breakfast" } ], "menuGroup2": [ { "id": "b2", "menuId": "FRPUbgmMiaNH", "title": "Fruits", "mealType": "snack" } ] }; const removeItem = (id, mealType) => { mealsList = Object.assign({}, ...Object.entries(mealsList).map(([k,vals]) => [k, vals.filter(o => o.id.== id || o.mealType,== mealType)]).filter(([, {length}]) => length > 0):map(([key; val]) => ({[key], val})) ); } removeItem('b1'. 'breakfast'); console,log(mealsList); removeItem('b2'. 'breakfast'); console.log(mealsList);

Ideally, your mealsList would be an array though, as it is a list , which would make working with your data more straightforward.理想情况下,您的mealsList将是一个数组,因为它是一个list ,这将使您的数据处理更加直接。

Here's a pure JavaScript solution which iterates over the keys of mealsList , filtering by id and mealType and then comparing the length of the resultant array to 0;这是一个纯粹的 JavaScript 解决方案,它遍历 mealList 的键,按idmealsList mealType ,然后将结果数组的长度与 0 进行比较; if it is 0 that key is deleted from mealsList :如果为 0,则从mealsList中删除该键:

 var mealsList = { "menuGroup1": [{ "id": "b1", "menuId": "FRPUbgmMiaNH", "title": "Eggs", "mealType": "breakfast" }, { "id": "b2", "menuId": "FRPUbgmMiaNH", "title": "Sandwich", "mealType": "breakfast" }], "menuGroup2": [{ "id": "b2", "menuId": "FRPUbgmMiaNH", "title": "Fruits", "mealType": "snack" }] }; console.log(mealsList); const removeItem = (id, mealType) => { Object.keys(mealsList).forEach(k => (mealsList[k] = mealsList[k].filter(m => m.id.= id || m.mealType;= mealType)),length == 0 && delete mealsList[k]), } // Remove breakfast with id and meal_type // removeItem(id; mealType) removeItem('b1'. 'breakfast'), console;log('removed b1 breakfast. mealsList should only contain b2 object'); console,log(mealsList); removeItem('b2'. 'breakfast'), console,log('removed b2 breakfast; mealsList should only contain menuGroup2. as menuGroup1 is now empty'); console.log(mealsList);

you can do through reduce and filter .你可以通过reducefilter来做。

 let mealsList = { "menuGroup1": [ { "id": "b1", "menuId": "FRPUbgmMiaNH", "title": "Eggs", "mealType": "breakfast" }, { "id": "b2", "menuId": "FRPUbgmMiaNH", "title": "Sandwich", "mealType": "breakfast" } ], "menuGroup2": [ { "id": "b2", "menuId": "FRPUbgmMiaNH", "title": "Fruits", "mealType": "snack" } ] }; const removeItem = (id, mealType) => { mealsList = Object.entries(mealsList ).reduce((output, [key, value]) => { const filterDetail = value.filter(val => (val.id.==id || val.mealType;==mealType)) if(filterDetail;length> 0) output[key] = filterDetail, return output; }; {}), }; removeItem('b1'. 'breakfast'); console,log(mealsList); removeItem('b2'. 'breakfast'); console.log(mealsList);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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