Tips for determining if an array of objects, into which I am adding objects, contains a particular key value present in a different array of objects

I've been working on this and here is what I have tried so far:

groceryList = [];

ngOnInit() {
  this._recipesSub = this.recipesService.recipes.subscribe((receivedData) => {
    this.loadedRecipes = receivedData.recipes;
  });
}
onCheckRecipe(e) {
    if (e.detail.checked === true) {
      let tickedRecipe = e.detail.value;
      let selectedRecipeIngredients;
      for (let recipe of this.loadedRecipes) {
        if (recipe.name === tickedRecipe) {
          selectedRecipeIngredients = recipe.ingredients;
        }
      }
      for (let selectedIng of selectedRecipeIngredients) {
        for (let existingIng of this.groceryList) {
          if (selectedIng.name) {
            this.groceryList.push(selectedIng);
          }
        }
      }
      console.log(this.groceryList);
    }
  }

When I check the console, I see the following output:

(8) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
0: {_id: "5f64ac1eb227fea1f63a5c99", name: "chia seeds", quantity: "10g"}
1: {_id: "5f64ac1eb227fea1f63a5c9a", name: "cherries", quantity: "15g"}
2: {_id: "5f64ac1eb227fea1f63a5c9b", name: "honey", quantity: "30g"}
3: {_id: "5f64ac1eb227fea1f63a5c9c", name: "almond flour", quantity: "10g"}
4: {_id: "5f64ac1eb227fea1f63a5c9e", name: "almond flour", quantity: "10g"}
5: {_id: "5f64ac1eb227fea1f63a5c9f", name: "egg", quantity: "10g"}
6: {_id: "5f64ac1eb227fea1f63a5ca0", name: "unsalted butter", quantity: "30g"}
7: {_id: "5f64ac1eb227fea1f63a5ca1", name: "peanut butter", quantity: "50g"}
length: 8
__proto__: Array(0)

My goal is to avoid having name: "almond flour" appear twice in the array. Instead, I want to combine the quantities like this:

{_id: "5f64ac1eb227fea1f63a5c9e", name: "almond flour", quantity: "20g"}

The desired functionality is to add each ingredient to the groceryList only if it's not already present. If an ingredient is already in the list, then just update its quantity.

I'm unsure about the approach to take to achieve this. Any suggestions or ideas would be greatly appreciated.

** Also the remove option

onCheckRecipe(e) {
    if (e.detail.checked === true) {
      for (let recipe of this.loadedRecipes) {
        if (recipe.name === e.detail.value) {
          recipe.ingredients.forEach((eachIngredient) => {
            let matchedIng = this.groceryList.find(function (foundIng) {
              return foundIng.name === eachIngredient.name;
            });
            if (matchedIng) {
              matchedIng.quantity =
                matchedIng.quantity + eachIngredient.quantity;
            } else {
              this.groceryList.push(eachIngredient);
            }
          });
        }
      }
    } else {
      for (let recipe of this.loadedRecipes) {
        if (recipe.name === e.detail.value) {
          recipe.ingredients.forEach((element) => {
            let matched = this.groceryList.find(function (foundIngre) {
              return foundIngre.name === element.name;
            });
            if (matched.quantity === element.quantity) {
              let index = this.groceryList.findIndex(
                (x) => x.name === matched.name
              );
              this.groceryList.splice(index, 1);
            } else {
              matched.quantity = matched.quantity - element.quantity;
            }
          });
        }
      }
    }
  }

Answer №1

Iterate through the ingredients array and utilize Array.prototype.find() method to search for a match in each loop. If a match is found, update the quantity; otherwise, add the ingredient object to the array.

An enhancement suggestion for simplifying calculations would be to introduce another field for units and store the quantity as a number. This would eliminate the need to extract units from a string for basic mathematical operations.

const ingredients = [{_id: "5f64ac1eb227fea1f63a5c9e", name: "almond flour", quantity: "10g"}];

ingredients.forEach(ingr => {
   // Find the matching object or returns undefined
   const wanted = data.find(({_id}) => _id === ingr._id);
   if(wanted){
     const {quantity: wq} = wanted,
           units = wq.match(/\D+/)[0];      
     wanted.quantity = parseInt(wq) + parseInt(ingr.quantity) + units;  
   }else{
     data.push(obj)
   }
})
 console.log(data)
.as-console-wrapper {max-height: 100%!important;top:0;}
<script>
const data =  [{_id: "5f64ac1eb227fea1f63a5c99", name: "chia seeds", quantity: "10g"},
 {_id: "5f64ac1eb227fea1f63a5c9a", name: "cherries", quantity: "15g"},
 {_id: "5f64ac1eb227fea1f63a5c9b", name: "honey", quantity: "30g"},
 {_id: "5f64ac1eb227fea1f63a5c9e", name: "almond flour", quantity: "10g"},
 
 {_id: "5f64ac1eb227fea1f63a5c9f", name: "egg", quantity: "10g"},
 {_id: "5f64ac1eb227fea1f63a5ca0", name: "unsalted butter", quantity: "30g"},
 {_id: "5f64ac1eb227fea1f63a5ca1", name: "peanut butter", quantity: "50g"}]
</script>

Answer №2

Check out my solution below:

const items = [
  { _id: "5f64ac1eb227fea1f63a5c99", name: "chia seeds", quantity: "10g" },
  { _id: "sdf7687hkksjj8881zzaooPP", name: "peanut butter", quantity: "20g" },
  { _id: "abcf781eb227fea1f63a5c9a", name: "cherries", quantity: "15g" },
  { _id: "5f64ac1eb227fea1f63a5c9b", name: "honey", quantity: "30g" },
  { _id: "5f64ac1eb227fea1f63a5c9c", name: "almond flour", quantity: "10g" },
  { _id: "5f64ac1eb227fea1f63a5c9e", name: "almond flour", quantity: "10g" },
  { _id: "5f64ac1eb227fea1f63a5c9f", name: "egg", quantity: "10g" },
  { _id: "ghg990c1eb227fea1f63a5c7", name: "egg", quantity: "19g" },
  { _id: "dsfsdffer340fea1f63a5ca0", name: "unsalted butter", quantity: "30g" },
  { _id: "5f64ac1eb227fea1f63a5ca1", name: "peanut butter", quantity: "50g" }
];

const shoppingList = items.reduce(
  (acc, item) => {
    const index = acc.findIndex(elt => elt.name === item.name);
    if (index !== -1) {
      const accQuantity = acc[index].quantity;
      const itemQuantity = item.quantity;
      const unit = accQuantity.match(/\D+/)[0];
      acc[index].quantity = +accQuantity.match(/\d+/)[0] + +itemQuantity.match(/\d+/)[0] + unit;
    } else {
      acc.push(item);
    }
    return acc;
  }, []
);
console.log(shoppingList);

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

Prevent page refresh when submitting a form using PureCSS while still keeping form validation intact

I'm currently implementing PureCSS forms into my web application and facing a challenge with maintaining the stylish form validation while preventing the page from reloading. I discovered that I can prevent the page reload by using onsubmit="return f ...

Laravel implementation of Bootstrap Datepicker

Incorporating Laravel bootstrap and a date picker, I have encountered an issue where the todayHighlight feature is not functioning correctly. Additionally, the container aspect is also not working as intended. <link rel="stylesheet" href="https://sta ...

Include a new module in the declarations NgModule utilizing ts-morph

Currently, I am utilizing the ts-morph library and my objective is to add a new component to the declarations: This is my initial setup: @NgModule({ declarations: [], imports: [], providers: [], }) Here is what I am aiming for: @NgModule({ declarations: [ ...

Ran into a situation where Nextjs13 had two children sharing the same key

Currently, I am in the process of creating a booking form using shadcn/ui within nextjs13. As part of this, I am mapping over different hairstyles listed in my postgres database to generate selectable options for users. However, during this process, I enco ...

The combination of Autodesk Forge Viewer and React with TypeScript provides a powerful platform for developing

I'm brand new to React and Typescript, and I have a very basic question. In the viewer documentation, extensions are defined as classes. Is it possible to transform that class into a typescript function? Does that even make sense? For example, take th ...

Error message encountered when attempting to export functions in Reactjs, resulting in an undefined function error in the context of Reactjs

As I work on creating an adaptive menu using Reactjs and Material UI, I have managed to complete everything. However, I encountered an issue when trying to import a const defined in a different file as the functions are not functioning as expected. The fu ...

What is the best method for resizing an SVG according to the size of my website's window?

I am attempting to implement a scalable settings icon SVG file that adjusts based on the window width. My approach involved creating a JavaScript function that alters the element's dimensions according to the window size, but unfortunately, this metho ...

Having trouble rendering a dynamic table with JavaScript utilizing a JSON object

I am struggling to retrieve data in JSON format and display it in a table. Despite trying various methods, I have been unable to make it work. Below is the code for this function. Can someone please assist me in identifying what is wrong with it? As of now ...

Here's a guide on how to display texts underneath icons in Buttons using Material UI

Currently, this is the Button I have displayed https://i.sstatic.net/YkHp0.png I am trying to figure out how to position the Dummy Button text beneath the icon. Can someone assist me with this? Below is my code snippet: <Button className={classes.d ...

Using indented, multi-line logging in a NodeJS environment can help to

I'm looking for a way to display objects that have been printed with JSON.stringify() in the console, specifically within the context of a Mocha test suite output. While my tests are running, I want the object log lines to be indented further to the ...

Issue encountered when trying to access the webpage through a puppeteer connection

I am currently experimenting with web scraping using the puppeteer library to extract data from a Chrome page. I have managed to connect to an existing Chrome page in debugging mode by obtaining the ws URL and successfully establishing a connection. Here i ...

What is the process of using JavaScript code to read a text file?

Trying to use Google Charts while reading data from a text file. The code in JS is written for this purpose: function readTextFile(file){ var rawFile = new XMLHttpRequest(); rawFile.open("GET", file, false); // using synchronous call var allTe ...

Converting blobs to strings and vice versa in Javascript

After successfully converting a blob to a string using FileReader, the challenge now is to convert it back: var reader = new window.FileReader(); reader.readAsDataURL(blob); reader.onloadend = function() { base64data = reader.result; var blobToSend ...

Set the position to fixed so it doesn't scroll

Is there a way to create a fixed position div that remains in place when the user scrolls, similar to the effect shown in this example image? Position Absolute: https://i.sstatic.net/4RAcc.png Position Fixed (desired effect): https://i.sstatic.net/3DIna. ...

Retrieving attribute values when using the .on function in jQuery

I currently have 10 links with the following format: <a href="#" data-test="test" class="testclass"></a> as well as a function that looks like this: $(document).on("click", ".testclass", function () { alert($(this).attr('data-t ...

What distinguishes res.send from app.post?

I'm just starting to learn about express and HTTP. I've heard that the express library has app.get, app.post, and res.send methods. From what I gather, app.get is used for GET requests and app.post is used for POST requests. How does res.send fit ...

What could be causing my Ionic button to not initialize in the expected state while using ngIf with a boolean property connected to an Ionic checkbox?

I'm currently in the process of setting up a list of ingredients with checkboxes and conditional buttons, but I'm facing some challenges with the default state. Ideally, I only want the button to be visible when the checkbox is unchecked so that ...

Using TypeScript to automatically deduce the output type of a function by analyzing the recursive input type

I am currently working on developing an ORM for a graph database using TypeScript. Specifically, I am focusing on enhancing the "find" method to retrieve a list of a specific entity. The goal is to allow the function to accept a structure detailing the joi ...

Choosing a specific category to display in a list format with a load more button for easier navigation

Things were supposed to be straightforward, but unexpected behaviors are popping up all over the place! I have a structured list like this XHTML <ul class = "query-list"> <li class="query"> something </li> <li class="query" ...

Leveraging previous state values within a setInterval function in React

Could someone please provide me with an answer to this topic? When I attempt to implement the Interval in the correct way (including cleanup), I encounter the following code: const [count,setCount] = useState(0) useEffect(() => { const interval = ...