[英]Lodash - search for item then remove other items that does not match in the object
I have this multidimensional array and I am doing a search and extracting them.我有这个多维数组,我正在搜索并提取它们。
This is what my object looks like:这是我的 object 的样子:
[
{
"id":1,
"name":"Hot Drinks",
"created_at":null,
"updated_at":null,
"menus":[
{
"id":1,
"name":"Brewed Coffee",
"price":"90.00",
"category_id":1,
"deleted_at":null,
"created_at":null,
"updated_at":null
},
{
"id":2,
"name":"Drip Coffee",
"price":"100.00",
"category_id":1,
"deleted_at":null,
"created_at":null,
"updated_at":null
},
{
"id":3,
"name":"Cappuccino",
"price":"100.00",
"category_id":1,
"deleted_at":null,
"created_at":null,
"updated_at":null
},
{
"id":4,
"name":"Caffe Latte",
"price":"100.00",
"category_id":1,
"deleted_at":null,
"created_at":null,
"updated_at":null
},
{
"id":5,
"name":"Caffe Mocha",
"price":"120.00",
"category_id":1,
"deleted_at":null,
"created_at":null,
"updated_at":null
}
]
},
{
"id":2,
"name":"Cold Drinks",
"created_at":null,
"updated_at":null,
"menus":[
{
"id":6,
"name":"Iced Coffee",
"price":"110.00",
"category_id":2,
"deleted_at":null,
"created_at":null,
"updated_at":null
},
{
"id":7,
"name":"Iced Latte",
"price":"120.00",
"category_id":2,
"deleted_at":null,
"created_at":null,
"updated_at":null
},
{
"id":8,
"name":"Iced Mocha",
"price":"140.00",
"category_id":2,
"deleted_at":null,
"created_at":null,
"updated_at":null
}
]
},
{
"id":3,
"name":"Beverages",
"created_at":null,
"updated_at":null,
"menus":[
]
},
{
"id":4,
"name":"Starters",
"created_at":null,
"updated_at":null,
"menus":[
{
"id":9,
"name":"Sizzling Sisig",
"price":"129.00",
"category_id":4,
"deleted_at":null,
"created_at":null,
"updated_at":null
},
{
"id":10,
"name":"Lumpia Shanghai",
"price":"149.00",
"category_id":4,
"deleted_at":null,
"created_at":null,
"updated_at":null
},
{
"id":11,
"name":"Pork & Shrimp Siomai",
"price":"169.00",
"category_id":4,
"deleted_at":null,
"created_at":null,
"updated_at":null
},
{
"id":12,
"name":"Spicy Tok Ramen",
"price":"159.00",
"category_id":4,
"deleted_at":null,
"created_at":null,
"updated_at":null
},
{
"id":14,
"name":"Humba Rice Meal",
"price":"110.00",
"category_id":4,
"deleted_at":null,
"created_at":null,
"updated_at":null
},
{
"id":15,
"name":"Siomai Rice Meal",
"price":"110.00",
"category_id":4,
"deleted_at":null,
"created_at":null,
"updated_at":null
},
{
"id":16,
"name":"Sisig Rice Meal",
"price":"110.00",
"category_id":4,
"deleted_at":null,
"created_at":null,
"updated_at":null
},
{
"id":18,
"name":"Suman (Pack of 6)",
"price":"110.00",
"category_id":4,
"deleted_at":null,
"created_at":null,
"updated_at":null
}
]
},
{
"id":5,
"name":"Rice Meals",
"created_at":null,
"updated_at":null,
"menus":[
{
"id":13,
"name":"Humba Rice Meal",
"price":"110.00",
"category_id":5,
"deleted_at":null,
"created_at":null,
"updated_at":null
},
{
"id":17,
"name":"Suman & Hot Choco",
"price":"140.00",
"category_id":5,
"deleted_at":null,
"created_at":null,
"updated_at":null
}
]
},
{
"id":6,
"name":"Desserts",
"created_at":null,
"updated_at":null,
"menus":[
]
}
]
This is how i do a search on the menus object.这就是我在菜单 object 上进行搜索的方式。
_.filter(this.originalMenus, {menus: [{name: _this.search}] });
The problem with this code is that if I searched "Brewed Coffee", it gets the entire menus
object instead of just the menus
object with just the "Brewed Coffee" that matches.这段代码的问题是,如果我搜索“Brewed Coffee”,它会得到整个
menus
object,而不仅仅是menus
object,其中只有匹配的“Brewed Coffee”。 So the returned result is like this, which is wrong:所以返回的结果是这样的,这是错误的:
[
{
"id":1,
"name":"Hot Drinks",
"created_at":null,
"updated_at":null,
"menus":[
{
"id":1,
"name":"Brewed Coffee",
"price":"90.00",
"category_id":1,
"deleted_at":null,
"created_at":null,
"updated_at":null
},
{
"id":2,
"name":"Drip Coffee",
"price":"100.00",
"category_id":1,
"deleted_at":null,
"created_at":null,
"updated_at":null
},
{
"id":3,
"name":"Cappuccino",
"price":"100.00",
"category_id":1,
"deleted_at":null,
"created_at":null,
"updated_at":null
},
{
"id":4,
"name":"Caffe Latte",
"price":"100.00",
"category_id":1,
"deleted_at":null,
"created_at":null,
"updated_at":null
},
{
"id":5,
"name":"Caffe Mocha",
"price":"120.00",
"category_id":1,
"deleted_at":null,
"created_at":null,
"updated_at":null
}
]
}
]
As you can see it included the other menu items which the Brewed Coffee belongs.如您所见,它包含了 Brewed Coffee 所属的其他菜单项。
How can I extract it that it looks like this:我怎样才能提取它看起来像这样:
[
{
"id":1,
"name":"Hot Drinks",
"created_at":null,
"updated_at":null,
"menus":[
{
"id":1,
"name":"Brewed Coffee",
"price":"90.00",
"category_id":1,
"deleted_at":null,
"created_at":null,
"updated_at":null
},
]
}
]
Apologies if I didn't explain it properly.抱歉,如果我没有正确解释它。
Another help if you can include it in your answer is that how can I do a search that partially matches the search, something like LIKE %search%
in MySQL.如果您可以将其包含在您的答案中,另一个帮助是我如何进行与搜索部分匹配的搜索,例如 MySQL 中的
LIKE %search%
。
Your help is greatly appreciated.非常感谢您的帮助。 Thank you.
谢谢你。
When use like this像这样使用的时候
_.filter(this.originalMenus, {menus: [{name: _this.search}] });
It will return all the object inside this.originalMenus
if {menus: [{name: _this.search}] }
gets passed.如果
{menus: [{name: _this.search}] }
被通过,它将返回 this.originalMenus 内的所有this.originalMenus
。
Basicaly it's filtering this.originalMenus
when {menus: [{name: _this.search}] }
gets passed, it's not filtering inner menus, inner menus are used as condition to filter the menu.基本上它在
{menus: [{name: _this.search}] }
被通过时过滤this.originalMenus
,它不是过滤内部菜单,内部菜单用作过滤菜单的条件。
so you might need to create a own filtering logic所以您可能需要创建自己的过滤逻辑
EX:前任:
function filterCofee(search) {
const filterdMenus = [];
menus.forEach(menu => {
// check if there's sub menus that we can filter.
var filterdMenu = _.filter(menu.menus, { name: search });
// if there's matches, then we will add it a array, and return it.
if (filterdMenu.length > 0) {
filterdMenus.push({
...menu,
menus: [...filterdMenu]
});
}
});
return filterdMenus;
}
filterCofee("Brewed Coffee")
and if you want to use it like LIKE %search%
, then replace the above filter with如果您想像
LIKE %search%
一样使用它,请将上面的过滤器替换为
// Here we are checking if the search text included in any of the name at any position.
var filterdMenu = _.filter(menu.menus, (m) => m.name.indexOf(search) >= 0);
You may also consider simply using plain vanilla Javascript您也可以考虑简单地使用普通香草 Javascript
const allMenus = [{ "id": 1, "name": "Hot Drinks", "created_at": null, "updated_at": null, "menus": [{ "id": 1, "name": "Brewed Coffee", "price": "90.00", "category_id": 1, "deleted_at": null, "created_at": null, "updated_at": null }, { "id": 2, "name": "Drip Coffee", "price": "100.00", "category_id": 1, "deleted_at": null, "created_at": null, "updated_at": null }, { "id": 3, "name": "Cappuccino", "price": "100.00", "category_id": 1, "deleted_at": null, "created_at": null, "updated_at": null }, { "id": 4, "name": "Caffe Latte", "price": "100.00", "category_id": 1, "deleted_at": null, "created_at": null, "updated_at": null }, { "id": 5, "name": "Caffe Mocha", "price": "120.00", "category_id": 1, "deleted_at": null, "created_at": null, "updated_at": null } ] }, { "id": 2, "name": "Cold Drinks", "created_at": null, "updated_at": null, "menus": [{ "id": 6, "name": "Iced Coffee", "price": "110.00", "category_id": 2, "deleted_at": null, "created_at": null, "updated_at": null }, { "id": 7, "name": "Iced Latte", "price": "120.00", "category_id": 2, "deleted_at": null, "created_at": null, "updated_at": null }, { "id": 8, "name": "Iced Mocha", "price": "140.00", "category_id": 2, "deleted_at": null, "created_at": null, "updated_at": null } ] }, { "id": 3, "name": "Beverages", "created_at": null, "updated_at": null, "menus": [ ] }, { "id": 4, "name": "Starters", "created_at": null, "updated_at": null, "menus": [{ "id": 9, "name": "Sizzling Sisig", "price": "129.00", "category_id": 4, "deleted_at": null, "created_at": null, "updated_at": null }, { "id": 10, "name": "Lumpia Shanghai", "price": "149.00", "category_id": 4, "deleted_at": null, "created_at": null, "updated_at": null }, { "id": 11, "name": "Pork & Shrimp Siomai", "price": "169.00", "category_id": 4, "deleted_at": null, "created_at": null, "updated_at": null }, { "id": 12, "name": "Spicy Tok Ramen", "price": "159.00", "category_id": 4, "deleted_at": null, "created_at": null, "updated_at": null }, { "id": 14, "name": "Humba Rice Meal", "price": "110.00", "category_id": 4, "deleted_at": null, "created_at": null, "updated_at": null }, { "id": 15, "name": "Siomai Rice Meal", "price": "110.00", "category_id": 4, "deleted_at": null, "created_at": null, "updated_at": null }, { "id": 16, "name": "Sisig Rice Meal", "price": "110.00", "category_id": 4, "deleted_at": null, "created_at": null, "updated_at": null }, { "id": 18, "name": "Suman (Pack of 6)", "price": "110.00", "category_id": 4, "deleted_at": null, "created_at": null, "updated_at": null } ] }, { "id": 5, "name": "Rice Meals", "created_at": null, "updated_at": null, "menus": [{ "id": 13, "name": "Humba Rice Meal", "price": "110.00", "category_id": 5, "deleted_at": null, "created_at": null, "updated_at": null }, { "id": 17, "name": "Suman & Hot Choco", "price": "140.00", "category_id": 5, "deleted_at": null, "created_at": null, "updated_at": null } ] }, { "id": 6, "name": "Desserts", "created_at": null, "updated_at": null, "menus": [ ] } ] const filterBy = (search) => allMenus.map( menu => ({...menu, menus: menu.menus.filter(({ name }) => name.includes(search)) }) ).filter(({menus}) => menus.length > 0) console.log(filterBy("Brewed Coffee"))
So _.filter
is going to return true or false for every element in an array and return the array.所以
_.filter
将为数组中的每个元素返回 true 或 false 并返回数组。 Because you are filter your top level menus ("Hot Drinks", "Cold Drinks"), the whole thing will be return there if it matches your predicate.因为您正在过滤您的顶级菜单(“热饮”、“冷饮”),所以如果它与您的谓词匹配,则整个内容将返回那里。
You may be better off using the es6 .map
function and passing in your own custom function to filter and map the object as you want it to. You may be better off using the es6
.map
function and passing in your own custom function to filter and map the object as you want it to. The .map
or .filter
functions are also where you'd be able to do your own logic for partial matches like you were asking. .map
或.filter
函数也是您可以为部分匹配执行自己的逻辑的地方,就像您要求的那样。
Otherwise you can do the following to essentially use lodash to do the filter, then use .map
to remove the extra items from the menus
array.否则,您可以执行以下操作以基本上使用 lodash 进行过滤,然后使用
.map
从menus
数组中删除额外的项目。
var filtered = _.filter(this.originalMenus, {menus: [{name: _this.search}] });
filtered.map(function(m,i){m.menus = _.filter(m.menus,{name: _this.search});
but I'd recommend something more along the lines of just using the .filter
and .map
functions like this但我会推荐更多类似这样的
.filter
和.map
函数
var filtered = originalMenus.filter((topMenu)=>
topMenu.menus.filter((sub)=>
sub.name.toLowerCase().includes(search.toLowerCase())).length > 0)
.map((m)=>
{return {...m, ...{menus:m.menus.filter((f)=>f.name.toLowerCase().includes(search.toLowerCase()))}}}
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.