Помогите собрать фильтр массива объектов js
Общая суть сайта(скрипта) выводить список рецептов из имеющихся ингредиентов в наличии. Все работает но столкнулся с такой мыслью что бурбон и виски по "сути" одно и тоже и стоило бы выводить рецепт имея или виски или бурбон но сейчас фильтр жестко привязан к конкретному ингредиенту, вопрос как сделать фильтр так чтоб рецепт выводился если есть виски или бурбон и это можно было как то указать в объекте рецепта с сохранением приоритета если есть оба напитка?
Имеем подобный массив
recipes = [
{
name: "Название1",
img: ".jpg",
ingr: ["whiskey", "liquor_triple_sec", "lemon_juice", "sugar_syrup", "sprite", "ice", "bild"],
size: ["30", "30", "15", "15", "120", "g150", " "],
description: "описание"
},
{
name: "Название2",
img: ".jpg",
ingr: ["bourbon", "liquor_triple_sec", "lemon_juice", "sugar_syrup", "sprite", "ice", "bild"],
size: ["30", "30", "15", "15", "120", "g150", " "],
description: "описание"
},
]
//этот массив содержит ингредиенты в наличии
b = ["bourbon", "whiskey", "liquor_triple_sec","lemon_juice", "sugar_syrup", "sprite", "ice", "bild"];
//сам фильтр
const res = recipes.filter(({ ingr }) => ingr.every(v => b.indexOf(v) !== -1));
Моя хотелка выглядит так, но js выбирает просто первое значение из или. Логика: есть только бурбон показывает 2 рецепта с бурбоном, если есть и виски и бурбон показывает 2 рецепта но один с бурбоном а другой с виски как указано в рецепте что первый напиток важнее
recipes = [
{
name: "Название1",
img: ".jpg",
ingr: [("bourbon" || "whiskey"), "liquor_triple_sec", "lemon_juice", "sugar_syrup", "sprite", "ice", "bild"],
size: ["30", "30", "15", "15", "120", "g150", " "],
description: "описание"
},
{
name: "Название2",
img: ".jpg",
ingr: [("whiskey" || "bourbon"), "liquor_triple_sec", "lemon_juice", "sugar_syrup", "sprite", "ice", "bild"],
size: ["30", "30", "15", "15", "120", "g150", " "],
description: "описание"
},
]
*.includes() запрещен сайт крутиться на телевизоре он его не понимает
Ответы (1 шт):
Простой вариант с небольшой модификацией объекта и кода. Альтернативные ингредиенты указываются в виде строки, разделенной |. При фильтрации такие строки режутся по разделителю и проверяется наличие хотя бы одного элемента. Приоритетность элемента внутри строки определяется порядком их следования, но данным кодом это не обрабатывается, это для бармена.
recipes = [{
name: "Название1",
img: ".jpg",
ingr: ["bourbon|whiskey", "liquor_triple_sec", "lemon_juice", "sugar_syrup", "sprite", "ice", "bild"],
size: ["30", "30", "15", "15", "120", "g150", " "],
description: "описание"
},
{
name: "Название2",
img: ".jpg",
ingr: ["whiskey|bourbon", "liquor_triple_sec", "lemon_juice", "sugar_syrup", "sprite", "ice", "bild"],
size: ["30", "30", "15", "15", "120", "g150", " "],
description: "описание"
},
{
name: "Название3",
img: ".jpg",
ingr: ["tequila|rum", "liquor_triple_sec", "lemon_juice", "sugar_syrup", "sprite", "ice", "bild"],
size: ["30", "30", "15", "15", "120", "g150", " "],
description: "описание"
}
]
b = ["bourbon", "whiskey", "liquor_triple_sec", "lemon_juice", "sugar_syrup", "sprite", "ice", "bild"];
const res = recipes.filter(({
ingr
}) => ingr.every(v => v.split('|').reduce((acc, curr) => acc + (b.indexOf(curr) !== -1), 0)));
console.log(res);
Если необходимо оставить только один приоритетный элемент из имеющихся в наличии ингредиентов, код может быть таким. Здесь сначала перебираются все рецепты, перед обработкой каждого устанавливается флаг absent=true (предполагаем, что исходно все ингредиенты есть). Далее перебираются все ингредиенты, которые сначала "сплитятся", а потом фильтруются - если какие-то из них есть, то формируется массив ненулевой длины, где элементы расположены в порядке следования (приоритета) - забираем первый, самый приоритетный элемент. Если же ни одного из ингредиентов нет, то устанавливается флаг absent=false. Далее в зависимости от состояния этого флага весь рецепт либо заносится в результирующий массив, либо нет. Если заносится, то предварительно меняется массив ингредиентов в нем на актуализированный с учетом их наличия и приоритетности.
recipes = [{
name: "Название1",
img: ".jpg",
ingr: ["bourbon|whiskey", "liquor_triple_sec", "lemon_juice", "sugar_syrup", "sprite", "ice", "bild"],
size: ["30", "30", "15", "15", "120", "g150", " "],
description: "описание"
},
{
name: "Название2",
img: ".jpg",
ingr: ["whiskey|bourbon", "liquor_triple_sec", "lemon_juice", "sugar_syrup", "sprite", "ice", "bild"],
size: ["30", "30", "15", "15", "120", "g150", " "],
description: "описание"
},
{
name: "Название3",
img: ".jpg",
ingr: ["tequila|rum", "liquor_triple_sec", "lemon_juice", "sugar_syrup", "sprite", "ice", "bild"],
size: ["30", "30", "15", "15", "120", "g150", " "],
description: "описание"
}
]
b = ["bourbon", "whiskey", "liquor_triple_sec", "lemon_juice", "sugar_syrup", "sprite", "ice", "bild"];
let res = [];
recipes.forEach(rec => {
inglist = [];
absent = false;
rec.ingr.forEach(i => {
f = i.split('|').filter(el => b.indexOf(el) !== -1)
if (f.length > 0) inglist.push(f[0]);
else absent = true;
})
if (!absent) {
rec.ingr = inglist;
res.push(rec);
}
})
console.log(res);