Home > OS >  Filtering an array of arrays with another array to return only combination of matching values
Filtering an array of arrays with another array to return only combination of matching values

Time:05-24

I have an array of objects containing information about cocktails such as ingredients, which I have fetched and sorted from an API.
This has been obtained by inputting an array of ingredients and receiving all possible cocktails containing said ingredients from the API.
I am trying to filter through this list and return the cocktails which have ingredients only found on the initial ingredient array. I want to know what drinks I can make from my ingredients and filter out the ones I cant. Below is my console data of my array of objects and a closer look at whats inside one object

(31) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
0:
dateModified: "2016-02-03 15:23:36"
idDrink: "16333"
strAlcoholic: "Alcoholic"
strCategory: "Punch / Party Drink"
strCreativeCommonsConfirmed: "No"
strDrink: "Adam Bomb"
strDrinkAlternate: null
strDrinkThumb: "https://www.thecocktaildb.com/images/media/drink/tpxurs1454513016.jpg"
strGlass: "Margarita/Coupette glass"
strIBA: null
strImageAttribution: null
strImageSource: null
strIngredient1: "Rum"
strIngredient2: "Vodka"
strIngredient3: "Tequila"
strIngredient4: "Triple sec"
strIngredient5: "Fruit"
strIngredient6: "Ice"
strIngredient7: "Salt"
strIngredient8: "Fruit juice"
strIngredient9: null
strIngredient10: null
strIngredient11: null
strIngredient12: null
strIngredient13: null
strIngredient14: null
strIngredient15: null
strInstructions: "Add ice to blender (or to glass if prefer on the rocks) then fruit, and fruite juice depending on personal prefference then add the Rum, Vodka, Tequila, and triple sec. blend till smooth, rim glass with sugar or salt and pour mixture in. garnish with lemon or lime slice."
strInstructionsDE: "Eis in den Mixer (oder in ein Glas, wenn Sie lieber On the Rocks bevorzugen), dann Obst und Fruchtsaft je nach persönlicher Vorliebe, dann Rum, Wodka, Tequila und Triple Sec. zugeben, bis sie glattflächig sind, Glas mit Zucker oder Salz einrühren und die Mischung hineingeben. Mit Zitronen- oder Limonenscheibe garnieren."
strInstructionsES: null
strInstructionsFR: null
strInstructionsIT: "Aggiungere il ghiaccio al frullatore (o al bicchiere se si preferisce con ghiaccio) poi la frutta e il succo di frutta a seconda delle preferenze personali, quindi aggiungere il rum, la vodka, la tequila e il triple sec.\r\nFrullare fino a che non diventa liscio, riempire l'orlo del bicchiere con zucchero o sale, e versare il composto.\r\nGuarnire con una fetta di limone o lime."
strInstructionsZH-HANS: null
strInstructionsZH-HANT: null
strMeasure1: "1 part "
strMeasure2: "1 part "
strMeasure3: "1 part "
strMeasure4: "1/2 part "
strMeasure5: null
strMeasure6: null
strMeasure7: "1-3 pint "
strMeasure8: null
strMeasure9: null
strMeasure10: null
strMeasure11: null
strMeasure12: null
strMeasure13: null
strMeasure14: null
strMeasure15: null
strTags: null
strVideo: null
[[Prototype]]: Object
1: {idDrink: '14364', strDrink: 'Aztec Punch', strDrinkAlternate: null, strTags: null, strVideo: null, …}
2: {idDrink: '17120', strDrink: 'Brain Fart', strDrinkAlternate: null, strTags: null, strVideo: null, …}
3: {idDrink: '13192', strDrink: 'National Aquarium', strDrinkAlternate: null, strTags: null, strVideo: null, …}
4: {idDrink: '16995', strDrink: 'Orange Whip', strDrinkAlternate: null, strTags: null, strVideo: null, …}
5: {idDrink: '16984', strDrink: 'Radioactive Long Island Iced Tea', strDrinkAlternate: null, strTags: null, strVideo: null, …}
6: {idDrink: '15300', strDrink: '3-Mile Long Island Iced Tea', strDrinkAlternate: null, strTags: null, strVideo: null, …}
7: {idDrink: '17015', strDrink: 'Irish Russian', strDrinkAlternate: null, strTags: null, strVideo: null, …}
8: {idDrink: '17204', strDrink: 'Long Island Iced Tea', strDrinkAlternate: null, strTags: 'IBA,ContemporaryClassic', strVideo: null, …}
9: {idDrink: '11002', strDrink: 'Long Island Tea', strDrinkAlternate: null, strTags: 'Strong,Asia,StrongFlavor,Brunch,Vegetarian,Sour', strVideo: null, …}
10: {idDrink: '15346', strDrink: '155 Belmont', strDrinkAlternate: null, strTags: null, strVideo: null, …}
11: {idDrink: '16943', strDrink: "A Gilligan's Island", strDrinkAlternate: null, strTags: null, strVideo: null, …}
12: {idDrink: '14272', strDrink: 'Addison Special', strDrinkAlternate: null, strTags: null, strVideo: null, …}
13: {idDrink: '15182', strDrink: 'After sex', strDrinkAlternate: null, strTags: null, strVideo: null, …}
14: {idDrink: '15849', strDrink: 'Apricot punch', strDrinkAlternate: null, strTags: null, strVideo: null, …}
15: {idDrink: '14622', strDrink: 'Arctic Fish', strDrinkAlternate: null, strTags: null, strVideo: null, …}
16: {idDrink: '17074', strDrink: 'Arizona Twister', strDrinkAlternate: null, strTags: null, strVideo: null, …}
17: {idDrink: '11119', strDrink: 'Blue Mountain', strDrinkAlternate: null, strTags: null, strVideo: null, …}
18: {idDrink: '14730', strDrink: 'Bubble Gum', strDrinkAlternate: null, strTags: null, strVideo: null, …}
19: {idDrink: '11462', strDrink: 'Harvey Wallbanger', strDrinkAlternate: null, strTags: 'IBA,ContemporaryClassic', strVideo: null, …}
20: {idDrink: '16987', strDrink: 'Irish Curdling Cow', strDrinkAlternate: null, strTags: null, strVideo: null, …}
21: {idDrink: '15330', strDrink: 'Orange Crush', strDrinkAlternate: null, strTags: null, strVideo: null, …}
22: {idDrink: '16995', strDrink: 'Orange Whip', strDrinkAlternate: null, strTags: null, strVideo: null, …}
23: {idDrink: '16992', strDrink: 'Pink Penocha', strDrinkAlternate: null, strTags: null, strVideo: null, …}
24: {idDrink: '13072', strDrink: 'Popped cherry', strDrinkAlternate: null, strTags: null, strVideo: null, …}
25: {idDrink: '15184', strDrink: 'San Francisco', strDrinkAlternate: null, strTags: null, strVideo: null, …}
26: {idDrink: '12162', strDrink: 'Screwdriver', strDrinkAlternate: null, strTags: 'IBA', strVideo: 'https://www.youtube.com/watch?v=ce_YOgaEo3Q', …}
27: {idDrink: '17267', strDrink: 'Bahama Mama', strDrinkAlternate: null, strTags: null, strVideo: null, …}
28: {idDrink: '16995', strDrink: 'Orange Whip', strDrinkAlternate: null, strTags: null, strVideo: null, …}
29: {idDrink: '14978', strDrink: 'Rum Punch', strDrinkAlternate: null, strTags: null, strVideo: null, …}
30: {idDrink: '16995', strDrink: 'Orange Whip', strDrinkAlternate: null, strTags: null, strVideo: null, …}
length: 31
[[Prototype]]: Array(0)

[![Array of objects containing drink information][1]][1]

I have tried to turn the objects into an array and filter them to show only the ingredients to make handling the data easier, and then tried to filter the data against my ingredients array.. but i've had no luck! I've looked at other questions but I can't seem to translate them to this problem.

//Map array list, convert each drink object into key:value array of arrays
        const ingList = fullList.map(drink => {
            const ingArray = Object.entries(drink)
//Filter out so we only have drink id and ingredients
            const ingFilter = ingArray.filter(x => x[0].includes('strIngredient') && x[1] !== null || x[0].includes('idDrink')) 
            return ingFilter
        })
        console.log(ingList)
 let result = []
        ingList.map(x => {
            let res = x.filter(item => ingredients.includes(item[1]))
            result.push(res)
        })   
        console.log(result)

Below is subset data from my console:

(31) [Array(9), Array(5), Array(7), Array(7), Array(6), Array(9), Array(10), Array(5), Array(7), Array(7), Array(5), Array(5), Array(4), Array(4), Array(6), Array(6), Array(10), Array(6), Array(5), Array(4), Array(5), Array(4), Array(6), Array(6), Array(5), Array(5), Array(3), Array(8), Array(6), Array(6), Array(6)]
0: Array(9)
0: (2) ['idDrink', '16333']
1: (2) ['strIngredient1', 'Rum']
2: (2) ['strIngredient2', 'Vodka']
3: (2) ['strIngredient3', 'Tequila']
4: (2) ['strIngredient4', 'Triple sec']
5: (2) ['strIngredient5', 'Fruit']
6: (2) ['strIngredient6', 'Ice']
7: (2) ['strIngredient7', 'Salt']
8: (2) ['strIngredient8', 'Fruit juice']
length: 9
[[Prototype]]: Array(0)
1: (5) [Array(2), Array(2), Array(2), Array(2), Array(2)]
2: (7) [Array(2), Array(2), Array(2), Array(2), Array(2), Array(2), Array(2)]
3: (7) [Array(2), Array(2), Array(2), Array(2), Array(2), Array(2), Array(2)]
4: (6) [Array(2), Array(2), Array(2), Array(2), Array(2), Array(2)]
5: (9) [Array(2), Array(2), Array(2), Array(2), Array(2), Array(2), Array(2), Array(2), Array(2)]
6: (10) [Array(2), Array(2), Array(2), Array(2), Array(2), Array(2), Array(2), Array(2), Array(2), Array(2)]
7: (5) [Array(2), Array(2), Array(2), Array(2), Array(2)]
8: (7) [Array(2), Array(2), Array(2), Array(2), Array(2), Array(2), Array(2)]
9: (7) [Array(2), Array(2), Array(2), Array(2), Array(2), Array(2), Array(2)]
10: (5) [Array(2), Array(2), Array(2), Array(2), Array(2)]
11: (5) [Array(2), Array(2), Array(2), Array(2), Array(2)]
12: (4) [Array(2), Array(2), Array(2), Array(2)]
13: (4) [Array(2), Array(2), Array(2), Array(2)]
14: (6) [Array(2), Array(2), Array(2), Array(2), Array(2), Array(2)]
15: (6) [Array(2), Array(2), Array(2), Array(2), Array(2), Array(2)]
16: (10) [Array(2), Array(2), Array(2), Array(2), Array(2), Array(2), Array(2), Array(2), Array(2), Array(2)]
17: (6) [Array(2), Array(2), Array(2), Array(2), Array(2), Array(2)]
18: (5) [Array(2), Array(2), Array(2), Array(2), Array(2)]
19: (4) [Array(2), Array(2), Array(2), Array(2)]
20: (5) [Array(2), Array(2), Array(2), Array(2), Array(2)]
21: (4) [Array(2), Array(2), Array(2), Array(2)]
22: (6) [Array(2), Array(2), Array(2), Array(2), Array(2), Array(2)]
23: (6) [Array(2), Array(2), Array(2), Array(2), Array(2), Array(2)]
24: (5) [Array(2), Array(2), Array(2), Array(2), Array(2)]
25: (5) [Array(2), Array(2), Array(2), Array(2), Array(2)]
26: (3) [Array(2), Array(2), Array(2)]
27: (8) [Array(2), Array(2), Array(2), Array(2), Array(2), Array(2), Array(2), Array(2)]
28: (6) [Array(2), Array(2), Array(2), Array(2), Array(2), Array(2)]
29: (6) [Array(2), Array(2), Array(2), Array(2), Array(2), Array(2)]
30: (6) [Array(2), Array(2), Array(2), Array(2), Array(2), Array(2)]
length: 31
[[Prototype]]: Array(0)

Full code below:

const ingredients = ['Vodka', 'Rum', 'Coca-cola', 'Orange Juice']

function getCombinations(valuesArray) {

    let combi = [];
    let temp = [];
    let slent = Math.pow(2, valuesArray.length);

    for (let i = 0; i < slent; i  )
    {
        temp = [];
        for (let j = 0; j < valuesArray.length; j  )
        {
            if ((i & Math.pow(2, j)))
            {
                temp.push(valuesArray[j]);
            }
        }
        if (temp.length > 0)
        {
            combi.push(temp);
        }
    }

    combi.sort((a, b) => a.length - b.length);
    // console.log(combi.join("\n"));
    // console.log(combi.filter(x => x.length > 1))
    combi = combi.filter(x => x.length > 1)
// Fetch data with combinations array    
    let drinkList = []
    const fetchAll = async (combi) => {
        for (let i = 0; i < combi.length; i  ) {
            let possible = await axios.get(`https://www.thecocktaildb.com/api/json/v2/9973533/filter.php?i=${combi[i].join(',')}`)
            let data = possible.data.drinks
            // console.log(possible.data.drinks)
            typeof(data) !== 'string' && drinkList.push(data)
        }
       // console.log(drinkList)
        //flatten array of arrays into one.
        const concatList = drinkList.flat(1)
        //console.log(concatList)
        let fullList = []
        //lookup each drink into new array with full details
        for (let i = 0; i < concatList.length; i  ) {
            let res = await axios.get(`https://www.thecocktaildb.com/api/json/v2/9973533/lookup.php?i=${concatList[i].idDrink}`)
            let data = res.data.drinks
            fullList.push(data)
        }
        //Flatten array of arrays into single array
        fullList = fullList.flat(1)
        console.log(fullList)

        //Map array list, convert each drink object into key:value array of arrays
        const ingList = fullList.map(drink => {
            const ingArray = Object.entries(drink)
        //Filter out so we only have drink id and ingredients
            const ingFilter = ingArray.filter(x => x[0].includes('strIngredient') && x[1] !== null || x[0].includes('idDrink')) 
            return ingFilter
        })
        console.log(ingList)
        
        let result = []
        ingList.map(x => {
            let res = x.filter(item => ingredients.includes(item[1]))
            result.push(res)
        })   
        console.log(result)   
            // var arr1 = [1,2,3,4],
            // arr2 = [2,4],
            // res = arr1.filter(item => !arr2.includes(item));
            // console.log(res);
    }
    fetchAll(combi)
}
getCombinations(ingredients);

CodePudding user response:

I think you can use the filter function something like below

let response = [{
    dateModified: "2016-02-03 15:23:36",
    idDrink: "16333",
    strAlcoholic: "Alcoholic",
    strCategory: "Punch / Party Drink",
    strCreativeCommonsConfirmed: "No",
    strDrink: "Adam Bomb",
    strDrinkAlternate: null,
    strDrinkThumb:
      "https://www.thecocktaildb.com/images/media/drink/tpxurs1454513016.jpg",
    strGlass: "Margarita/Coupette glass",
    strIBA: null,
    strImageAttribution: null,
    strImageSource: null,
    strIngredient1: "Rum",
    strIngredient2: "Vodka",
    strIngredient9: null,
    strIngredient10: null,
    strIngredient11: null,
    strIngredient12: null,
    strIngredient13: null,
    strIngredient14: null,
    strIngredient15: null,
    strInstructions:
      "Add ice to blender (or to glass if prefer on the rocks) then fruit, and fruite juice depending on personal prefference then add the Rum, Vodka, Tequila, and triple sec. blend till smooth, rim glass with sugar or salt and pour mixture in. garnish with lemon or lime slice.",
    strInstructionsDE:
      "Eis in den Mixer (oder in ein Glas, wenn Sie lieber On the Rocks bevorzugen), dann Obst und Fruchtsaft je nach persönlicher Vorliebe, dann Rum, Wodka, Tequila und Triple Sec. zugeben, bis sie glattflächig sind, Glas mit Zucker oder Salz einrühren und die Mischung hineingeben. Mit Zitronen- oder Limonenscheibe garnieren.",
    strInstructionsES: null,
    strInstructionsFR: null,
    strInstructionsIT:
      "Aggiungere il ghiaccio al frullatore (o al bicchiere se si preferisce con ghiaccio) poi la frutta e il succo di frutta a seconda delle preferenze personali, quindi aggiungere il rum, la vodka, la tequila e il triple sec.\r\nFrullare fino a che non diventa liscio, riempire l'orlo del bicchiere con zucchero o sale, e versare il composto.\r\nGuarnire con una fetta di limone o lime.",
    strMeasure1: "1 part ",
    strMeasure2: "1 part ",
    strMeasure3: "1 part ",
    strMeasure4: "1/2 part ",
    strMeasure5: null,
    strMeasure6: null,
    strMeasure7: "1-3 pint ",
    strMeasure8: null,
    strMeasure9: null,
    strMeasure10: null,
    strMeasure11: null,
    strMeasure12: null,
    strMeasure13: null,
    strMeasure14: null,
    strMeasure15: null,
    strTags: null,
    strVideo: null
  }];

const INGREDIENTS = ["Vodka", "Rum", "Coca-cola", "Orange Juice"];

function filterList(listOfCocktails) {
  return listOfCocktails.filter((cocktail) => {
    let isIngredientPresent = true;
    Object.keys(cocktail).every((key) => {
      if (
        key.includes("strIngredient") &&
        cocktail[key] &&
        !INGREDIENTS.includes(cocktail[key])
      ) {
        isIngredientPresent = false;
        return false;
      } else {
        return true;
      }
    });
    return isIngredientPresent;
  });
}

console.log(filterList(response));

CodePudding user response:

I managed to solve it like so :

  let resultMap = fullList.map(drink => {
            for (let i = 1; i <= 15; i  ) {
                console.log(drink[`strIngredient${i}`])
                if (drink[`strIngredient${i}`] !== null && ingredients.indexOf(drink[`strIngredient${i}`]) === -1) {
                    valid = false;
                    break;
                } else {
                    valid = true;
                }
            }
            console.log(valid)
            valid === true && result.push(drink)            
        })

        console.log(result)

  • Related