Fill an array with four distinct, random objects without any duplicates using ES6+ and apply specific filters

I could use some assistance enhancing a function that populates an array with 4 random, non-repeating recipe objects based on their IDs. However, I now need to incorporate an additional requirement where the recipes must include one breakfast, one lunch, one snack, and one dinner item. For instance:

Here is an example of JSON containing recipes:

[
  {
    recipeId: 1,
    recipeTypeId: 1, // Breakfast
    "description": "someRecipe",
    "img": "someImgBase64",
  },
  {
    recipeId: 2,
    recipeTypeId: 2, // Lunch
    "description": "someRecipe",
    "img": "someImgBase64",
  },
  {
    recipeId: 3,
    recipeTypeId: 3, // Snack
    "description": "someRecipe",
    "img": "someImgBase64",
  },
  {
    recipeId: 4,
    recipeTypeId: 4, // Dinner
    "description": "someRecipe",
    "img": "someImgBase64",
  },
  {
    recipeId: 5,
    recipeTypeId: 1, // Breakfast
    "description": "someRecipe",
    "img": "someImgBase64",
  }
]

This is my current function:

randomRecipes() {
  // Retrieve previously saved recipes from API
  localStorage.getItem('recipesList');
  // Random number generator
  const randomIndex = new Set();
  const recommendedRandomRecipes: [] = [];
  while (randomIndex.size < 4) {
    randomIndex.add(Math.floor(Math.random() * recipes.length));
  }
  randomIndex.forEach(i => recommendedRandomRecipes.push(recipes[Number(i)]));
  localStorage.addItem('recommendedRecipes', recommendedRandomRecipes);
  this.recipes = recommendedRandomRecipes;
}

The desired outcome:

recommendedRandomRecipes [1,2,3,4] or [2,3,4,5]

What I want to avoid:

RecommendedRandomRecipes [1,2,3,5] // Multiple breakfast items in the array

Answer №1

One method to achieve this task is by creating a list of recipes that feature only one randomly selected recipe per recipeTypeId. Below are the steps to follow in order to accomplish this:

  1. Start by iterating through the array to gather all distinct values for recipeTypeId. Utilize new Set() for this purpose.
  2. Next, loop through these unique recipe types. For each type, filter the original recipes list to create an array consisting of recipes belonging to that specific type. Then, select a random item from this filtered array by referring to this guide on how to pick a random item.
  3. Gather all these chosen items and provide only their respective recipeId.
  4. If needed, arrange them in ascending order according to your output preference.

Check out the proof-of-concept below:

const recipesList = [
  {
    recipeId: 1,
    recipeTypeId: 1, // Breakfast
    "description": "someRecipe",
    "img": "someImgBase64",
  },
  {
    recipeId: 2,
    recipeTypeId: 2, // Lunch
    "description": "someRecipe",
    "img": "someImgBase64",
  },
  {
    recipeId: 3,
    recipeTypeId: 3, // Snack
    "description": "someRecipe",
    "img": "someImgBase64",
  },
  {
    recipeId: 4,
    recipeTypeId: 4, // Dinner
    "description": "someRecipe",
    "img": "someImgBase64",
  },
  {
    recipeId: 5,
    recipeTypeId: 1, // Breakfast
    "description": "someRecipe",
    "img": "someImgBase64",
  }
];

// Obtain unique recipeTypeId
const recipeTypes = new Set();
recipesList.forEach((recipe) => recipeTypes.add(recipe.recipeTypeId));

// Iterate over unique recipe types and choose a random recipe
const recipeCombos = Array.from(recipeTypes).map((type) => {
  const filteredRecipesByType = recipesList.filter((recipe) => {
    return recipe.recipeTypeId === type;
  });
  
  // Select a random recipe from this filtered collection
  const randomRecipeByType = filteredRecipesByType[Math.floor(Math.random() * filteredRecipesByType.length)];
  
  // Return only the recipeId since that's the desired property
  return randomRecipeByType.recipeId;
});

// The possible combinations for your provided data are:
// [1,2,3,4]
// [2,3,4,5]
console.log(recipeCombos.sort());

Answer №2

Check out the code snippet below for detailed explanations:

var recipes = [
  {
    recipeId: 1,
    recipeTypeId: 1, // breakFast
    "description": "someRecipe",
    "img": "someImgBase64",
  },
  {
    recipeId: 2,
    recipeTypeId: 2, // lunch
    "description": "someRecipe",
    "img": "someImgBase64",
  },
  {
    recipeId: 3,
    recipeTypeId: 3, // snack
    "description": "someRecipe",
    "img": "someImgBase64",
  },
  {
    recipeId: 4,
    recipeTypeId: 4, // dinner
    "description": "someRecipe",
    "img": "someImgBase64",
  },
  {
    recipeId: 5,
    recipeTypeId: 1, // breakfast
    "description": "someRecipe",
    "img": "someImgBase64",
  }
]

function randomRecipes(recipes) {
  // 1. Counting the different recipeTypeIds present in the recipes array
  var recipeTypeIdsLegth = recipes.reduce((acc, item) => acc.indexOf(item.recipeTypeId) == -1 ? [...acc, item.recipeTypeId] : acc, []).length;
  console.log(recipeTypeIdsLegth) // 4

  // 2. Cloning the original array to modify it
  let clonedRecipes = [...recipes]

  // 3. Initializing an empty result array
  var recommendedRandomRecipes = []

  // 4. Iterating over the unique recipeTypeIds
  for (i = 0; i < recipeTypeIdsLegth; i++) {
    
    // 5. Generating a random index
    var randomIndex = Math.floor(Math.random() * clonedRecipes.length);

    // 6. Adding the randomly chosen recipe to the result array
    recommendedRandomRecipes.push(clonedRecipes[randomIndex]);

    // 7. Filtering out recipes with the same recipeTypeId as the selected one
    clonedRecipes = clonedRecipes.filter(item => item.recipeTypeId !== clonedRecipes[randomIndex].recipeTypeId)
  }

  // 8. Returning the recommended random recipes
  return recommendedRandomRecipes;
}

var recommendedRandomRecipes = randomRecipes(recipes);

console.log(recommendedRandomRecipes);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Setting a maximum value for a text box input in Angular for enhanced bot functionality

Currently, I am working with Angular 7 and I find myself trying to incorporate the min and max properties into a textbox. However, I seem to be encountering some difficulties in achieving this. <div> <input type='text' [(ngModel)]= ...

Sort booleans in reverse order in TypeScript in descending order

Having an issue with boolean sorting I have this specific function sortExt() { this.usersChoose.sort(function(a, b) { return a.EXT - b.EXT }) } Triggered by this button <button class="btn btn-info" (click)="sortExt()">Filter</but ...

Angular repeatedly displays user information

I am a beginner in the world of programming, teaching myself as I go along. Despite searching through numerous websites, I have struggled to find a solution to a persistent issue in my initial app while trying to grasp some fundamental concepts. Within Fi ...

Challenges with implementing Typescript in Next.js and the getStaticProps function

Having trouble with the implementation of getStaticProps where the result can be null or some data. The typings in getStaticProps are causing issues, even after trying conditional props. Any suggestions? type ProductType = { props: | { ...

The issue of data being duplicated when clicking on react-cookie-consent

Currently, I am utilizing the npm package https://www.npmjs.com/package/react-cookie-consent to implement a cookies consent feature in my react TypeScript application. However, I have encountered two issues with this package. Firstly, upon clicking the acc ...

The upload function does not allow re-uploading of a file that has been previously deleted

Attempting to upload a file using the following code onDrag(event:any) { console.log(this.toUpload); if(this.toUpload.length >0){ this.error = "Only one file at a time is accepted"; }else{ let fileName = event[0].name; let split ...

Passing an observable from parameters to a pipe in RxJS: A guide

Can someone help me with writing a TypeScript function like the one below: function abc(arg1, arg2, arg3) { pipe(arg1, arg2, arg3...); // or someSubject.pipe(arg1, arg2, arg3..) } I keep getting errors when trying to build the code. How can I success ...

Turn off basic authentication for serving static content with Spring Security

I am facing an issue with my setup where I have an Angular app served as static content from a Spring Boot app. The Angular app is located inside target/classes/static/index.html of the Spring Boot application. Additionally, I have a REST API served from t ...

Upgrading from Angular 4 to 9

What is the recommended approach for migrating from Angular 4 to 9 - should one go directly from 4 to 9, or is it better to first upgrade to version 7 and then to 9? ...

Adjusting the height of Google maps in Angular 4 to occupy the rest of the

I have integrated https://github.com/SebastianM/angular-google-maps into my angular 4 application. In order for the map to display properly, I need to specify the map height in CSS like this: agm-map { height: 300px; } Is there a way for the <agm-m ...

Combining and forming a distinctive case-sensitive array in JavaScript

Explaining a complex scenario, I have one object or array and one array. My goal is to compare selectedmodel values with mappedmodels. If the value (case insensitive) matches any key in the object, I need to fetch all associated values and push them into t ...

Problem with resizing the calendar dialog in PrimeNG's p-calendar component

When using the <p-calendar from PrimeNg, I encountered an issue regarding the size of the calendar. When I resize the navigator to 60%, the calendar is visible https://i.sstatic.net/AJ3dCtw8.png. However, when the zoom of the navigator is set to 100%, t ...

React: Unable to locate module: Unable to resolve

Currently, I am in the process of building a React App using Prisma, Apollo Client, and GraphQL-yoga. While following a tutorial on creating a GraphQL form in just 5 minutes, I encountered an issue that has left me stuck. ./src/components/CreateEntry.js M ...

TypeORM's OneToMany relationship creates a corresponding column in the database

I am working with three tables and entities: client store store_client The relationships between these entities are as follows: Client: @OneToMany((type) => StoreClient, (storeClient) => storeClient.client, { eager: false }) storeClient: StoreClie ...

What location is the optimal choice for documenting logs at a debugging level?

My team and I have been deeply contemplating the best location for writing a debug-level log during our development process. We are utilizing winston in conjunction with winston-daily-rotate-file to separate out different aspects of logging, as well as ne ...

Executing ngOnChanges in Angular 2

Within the Child component, there is an input field. Upon triggering the blur event, the value entered into this input field is passed to the AppComponent using an eventEmitter. This new value is then used to update the Key property of the AppComponent. Th ...

Guide for integrating a locally cloned open source angular component into your Angular project

Currently, I have an Angular 10 project that includes an open source Angular component installed via the typical "npm install --s xxxxxxx" method. My goal is to duplicate the github repository of this open source Angular component onto my local ...

Is there a method for the parent to detect changes in its output when passing around complex objects to its child?

I am facing a challenge with a complex object that is being passed down from a parent component to its child components. The child components further break down this object and pass parts of it to their own children, creating layers of complexity. At times ...

Building Interactive Graphs with Chart.JS in Angular Using Observables

Having some difficulty setting up a Chart with Angular and Chart.JS. I'm struggling to pass my Observable data into the Chart, no matter what I try. error TS2339: Property 'cool_data' does not exist on type 'Observable<Object>&a ...

Unable to locate the type definition file for 'jquery'

After updating my NuGet packages, I encountered an issue where I can no longer compile due to an error related to the bootstrap definition file not being able to find the jquery definition file within my project. Prior to the update, the directory structu ...