<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jonathan Kulak</title>
    <description>The latest articles on DEV Community by Jonathan Kulak (@lakadaize).</description>
    <link>https://dev.to/lakadaize</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1389624%2F5b8b6a4c-5fac-4561-992d-a3447f4fdd59.jpg</url>
      <title>DEV Community: Jonathan Kulak</title>
      <link>https://dev.to/lakadaize</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lakadaize"/>
    <language>en</language>
    <item>
      <title>An (Im)mutable Shopping List for a Delicious Pesto Pasta</title>
      <dc:creator>Jonathan Kulak</dc:creator>
      <pubDate>Wed, 21 Aug 2024 00:34:34 +0000</pubDate>
      <link>https://dev.to/lakadaize/an-immutable-shopping-list-for-a-delicious-pesto-pasta-2jd6</link>
      <guid>https://dev.to/lakadaize/an-immutable-shopping-list-for-a-delicious-pesto-pasta-2jd6</guid>
      <description>&lt;h3&gt;
  
  
  Pesto pasta is proof that G-d exists
&lt;/h3&gt;

&lt;p&gt;There are few things in life that give me more pleasure than a heaping helping of fresh pesto over homemade Capellini (Angel Hair). I'm a bonafide foodie - especially when it comes to Italian cuisine - and am always trying more complex recipes, but the simplicity and enjoyment of such a minimalist dish never ceases to satisfy. If I had the (mis)fortune of choosing a last meal it would be a tough decision between sushi and pesto over pasta, but I still think pesto pasta wins out in the end. &lt;/p&gt;

&lt;h3&gt;
  
  
  All this talk of pesto is making me hungry
&lt;/h3&gt;

&lt;p&gt;What am I to do? Well, make pesto pasta of course. Sometimes you just gotta say, "&lt;a href="https://www.youtube.com/watch?v=l9qWna_PyDw" rel="noopener noreferrer"&gt;Quando a Roma!&lt;/a&gt;" &lt;/p&gt;

&lt;p&gt;Lets start by making a list of ingredients to buy from our friendly Italian Market, "Il Mercato di Giovanni." We will create our shopping list from two recipes using both immutable and mutable object arrays. While it would be more efficient to simply write out what we need, you know that this is just way more fun. I can tell you're &lt;strong&gt;starving&lt;/strong&gt; for more on how we can program our way to pesto pasta, so let's &lt;strong&gt;dig&lt;/strong&gt; right in. "Mangia Mangia!"&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating separate pasta and pesto recipe arrays
&lt;/h3&gt;

&lt;p&gt;We'll start by declaring variables for &lt;code&gt;pastaRecipeArray&lt;/code&gt; and &lt;code&gt;pestoRecipeArray&lt;/code&gt;, with each variable assigned to an array of objects, where each object represents an individual ingredient. &lt;/p&gt;

&lt;p&gt;When we assign array values to each variable we use the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze" rel="noopener noreferrer"&gt;Object.freeze()&lt;/a&gt; method to ensure that they are &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Immutable" rel="noopener noreferrer"&gt;immutable&lt;/a&gt;. &lt;em&gt;(more on this later)&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;Each recipe object has three properties, with key-value pairs as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;u&gt;'name'&lt;/u&gt; = The name of the ingredient in the form of a 'string'&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;'recipe'&lt;/u&gt; = A value or values, in the form of an 'array', indicating which recipe(s) the ingredient is needed for (pasta, pesto, or both)&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;'price'&lt;/u&gt; = The price of the ingredient in USD, in the form of a 'number', using fairly unrealistic dummy content&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;(note: I've ommitted quantities and other details to keep things brief and relatively simple in this post. We could also implement these objects using JSON, but we are keeping things easy to &lt;b&gt;digest&lt;/b&gt; here.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The code to establish these arrays will look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const pastaRecipeArray = Object.freeze([
  { "name": "Eggs", "recipe": ["pasta"], "price": 6.99 },
  { "name": "Extra Virgin Olive Oil", "recipe": ["pasta", "pesto"], "price": 12.59 },
  { "name": "Kosher Salt", "recipe": ["pasta", "pesto"], "price": 7.89 },
  { "name": "Semolina Flour", "recipe": ["pasta"], "price": 12.95 }
])

const pestoRecipeArray = Object.freeze([
  { "name": "Basil", "recipe": ["pesto"], "price": 6.99 },
  { "name": "Black Pepper", "recipe": ["pesto"], "price": 9.99 },
  { "name": "Extra Virgin Olive Oil", "recipe": ["pasta", "pesto"], "price": 12.59 },
  { "name": "Kosher Salt", "recipe": ["pasta", "pesto"], "price": 7.89 },
  { "name": "Parmesan", "recipe": ["pesto"], "price": 15.99 },
  { "name": "Pine Nuts", "recipe": ["pesto"], "price": 13.98 }
])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll notice again that the &lt;code&gt;recipe&lt;/code&gt; key points to a value that is in the form of an array. We set it up this way because some ingredients are used in both recipes.&lt;/p&gt;

&lt;p&gt;To test that &lt;code&gt;pastaRecipeArray&lt;/code&gt; is set up properly we can utilize the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach" rel="noopener noreferrer"&gt;.forEach()&lt;/a&gt; method, a callback function used to iterate over each object in the array. Using &lt;code&gt;ingredient&lt;/code&gt; as the parameter, we can log it into the console as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pastaRecipeArray.forEach((ingredient) =&amp;gt; {
  console.log(ingredient)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you inspect the console you should see something like the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Object {name: "Eggs", recipe: Array(1), price: 6.99}
Object {name: "Extra Virgin Olive Oil", recipe: Array(2), price: 12.59}
Object {name: "Kosher Salt", recipe: Array(2), price: 7.89}
Object {name: "Semolina Flour", recipe: Array(1), price: 12.95}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similarly, we can log our &lt;code&gt;pestoRecipeArray&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pestoRecipeArray.forEach((ingredient) =&amp;gt; {
  console.log(ingredient)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which results in the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Object {name: "Basil", recipe: Array(1), price: 6.99}
Object {name: "Black Pepper", recipe: Array(1), price: 9.99}
Object {name: "Extra Virgin Olive Oil", recipe: Array(2), price: 12.59}
Object {name: "Kosher Salt", recipe: Array(2), price: 7.89}
Object {name: "Parmesan", recipe: Array(1), price: 15.99}
Object {name: "Pine Nuts", recipe: Array(1), price: 13.98}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;(note: When you see output such as &lt;code&gt;Array(1)&lt;/code&gt; and &lt;code&gt;Array(2)&lt;/code&gt; you would either want to rewrite the function to select those keys or simply click on the array in the console to see the details of what it contains.)&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a Shopping List Array
&lt;/h3&gt;

&lt;p&gt;Now that we've established our recipe arrays we want to move on to the next step, creating a shopping list array. To do this we will want to combine our object arrays &lt;code&gt;pastaRecipeArray&lt;/code&gt; and &lt;code&gt;pestoRecipeArray&lt;/code&gt; into a new mutable variable named &lt;code&gt;shoppingListArray&lt;/code&gt;. We will do this using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax" rel="noopener noreferrer"&gt;spread operator&lt;/a&gt; &lt;code&gt;...&lt;/code&gt; like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const shoppingListArray = [...pastaRecipeArray, ...pestoRecipeArray]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's use the following &lt;code&gt;console.log()&lt;/code&gt; to see what our new list looks like. Moving forward we will log property values within the object rather than the full object, to remove some of the clutter. You will want to use this code to see how our list changes after each step of the process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;shoppingListArray.forEach((ingredient) =&amp;gt; {
      console.log(ingredient.name)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see that our lists have been joined together into one in the console, this time only logging each ingredient &lt;code&gt;name&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Eggs
Extra Virgin Olive Oil
Kosher Salt
Semolina Flour
Basil
Black Pepper
Extra Virgin Olive Oil
Kosher Salt
Parmesan
Pine Nuts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Immutable vs. mutable arrays
&lt;/h3&gt;

&lt;p&gt;Why should we make &lt;code&gt;pastaRecipeArray&lt;/code&gt; and &lt;code&gt;pestoRecipeArray&lt;/code&gt; &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Immutable" rel="noopener noreferrer"&gt;immutable&lt;/a&gt;? Making them immutable makes it so that we can't change their values after they are assigned. We don't want to just tear these recipes up. We want to save them for another glorious day. Those immutable family recipes need to live on, regardless of what we are about to write on our temporary, mutable shopping list. &lt;/p&gt;

&lt;p&gt;We also want to be able to add or substract ingredients from our newly created &lt;code&gt;shoppingListArray&lt;/code&gt; to make this dish to our specific tastes, without affecting our original recipes of course. &lt;/p&gt;

&lt;h3&gt;
  
  
  Adding, replacing, and deleting ingredients
&lt;/h3&gt;

&lt;p&gt;As you may have noticed, when we combined our pasta and pesto recipes into our shopping list we ended up with duplicates for "Extra Virgin Olive Oil" and "Kosher Salt". We don't need to buy these twice so let's get rid of them. There are fancier ways to eliminate duplicates, but for now we will use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice" rel="noopener noreferrer"&gt;.splice()&lt;/a&gt; to remove the first &lt;code&gt;Extra Virgin Olive Oil&lt;/code&gt; object. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;.splice()&lt;/code&gt; method destructively deletes or replaces elements in an array. The first parameter represents the first element we are deleting and the second parameter represents how many elements we want to delete from that start point. While "Extra Virgin Olive Oil" is the second object in the array, arrays start at '0', so technically the second object is represented by a '1'. Let's execute the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;shoppingListArray.splice(1, 1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the console you will see that there is now only one "Extra Virgin Olive Oil" object. &lt;em&gt;(note: If you try to use &lt;code&gt;.splice()&lt;/code&gt; or similar methods on one of our original recipe arrays you will get a TypeError because we used &lt;code&gt;Object.freeze()&lt;/code&gt;, making them immutable.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We still have an extra "Kosher Salt", and now we are going to use &lt;code&gt;.splice()&lt;/code&gt; to it's full power. In addition to our first two parameters we have a third parameter that can replace elements in an array with new elements. I love to add a bit of lemon to my pesto, and I don't like food that is too salty, so let's go ahead and replace our extra "Kosher Salt" with our new "Lemon" object. We will declare our &lt;code&gt;lemon&lt;/code&gt; object as a variable for better readibility and include it as the third &lt;code&gt;.splice()&lt;/code&gt; parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const lemon = { "name": "Lemon", "recipe": ["pesto"], "price": 2.04 }

shoppingListArray.splice(6, 1, lemon)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Today I'm feeling a bit &lt;b&gt;saucy&lt;/b&gt; so let's change things up a bit and add in some roasted tomatoes using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push" rel="noopener noreferrer"&gt;.push()&lt;/a&gt;. With &lt;code&gt;.push()&lt;/code&gt; we can add elements to the end of the array, with each parameter representing a new element.  So let's add some "Cherry Tomatoes" to our list. Come to think of it, I forgot the "Garlic" too!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const tomatoes = { "name": "Cherry Tomatoes", "recipe": ["pesto"], "price": 5.99 }

const garlic = { "name": "Garlic", "recipe": ["pesto"], "price": 2.99 }

shoppingListArray.push(tomatoes, garlic)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Organizing our shopping list
&lt;/h3&gt;

&lt;p&gt;Now that we have all our ingredients well established let's organize them in a way that will make our shopping experience seamless.&lt;/p&gt;

&lt;p&gt;Let's organize our list alphabetically using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort" rel="noopener noreferrer"&gt;.sort()&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;shoppingListArray.sort((a, b) =&amp;gt; {
  const nameA = a.name
  const nameB = b.name

  if (nameA &amp;lt; nameB) {
    return -1
  }
  if (nameA &amp;gt; nameB) {
    1
  }
  return 0
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our shopping list now looks like this in the console.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Basil
Black Pepper
Cherry Tomatoes
Eggs
Extra Virgin Olive Oil
Garlic
Kosher Salt
Lemon
Parmesan
Pine Nuts
Semolina Flour
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Planning ahead for our expected costs
&lt;/h3&gt;

&lt;p&gt;Now we are ready to go to the market, but first let's make sure we know how much money we need, using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce" rel="noopener noreferrer"&gt;.reduce()&lt;/a&gt;.  There is a lot to go over with &lt;code&gt;.reduce()&lt;/code&gt;, and I'm getting hungry, so I'll skip over the details.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const ingredientsPrice = shoppingListArray.reduce((accumulator, ingredient) =&amp;gt; {
  return accumulator + ingredient.price
}, 0)

console.log("You will need $" + ingredientsPrice + " to make pesto pasta. Man is life is expensive.")
// You will need $98.39 to make pesto pasta. Wow, life is expensive.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating new recipe list arrays
&lt;/h3&gt;

&lt;p&gt;So we went to the store and got our ingredients, but now we want to separate our ingredients back into their respective recipes, just to lay everything out on the table and keep things in order. Lets create two new arrays, &lt;code&gt;pastaIngredients&lt;/code&gt; and &lt;code&gt;pestoIngredients&lt;/code&gt; using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter" rel="noopener noreferrer"&gt;.filter()&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes" rel="noopener noreferrer"&gt;.includes()&lt;/a&gt;, and of course &lt;code&gt;.forEach()&lt;/code&gt; to log them to the console.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const pastaIngredients = shoppingListArray.filter((ingredient) =&amp;gt; {
  return ingredient.recipe.includes('pasta')
})

pastaIngredients.forEach((ingredient) =&amp;gt; {
  console.log(ingredient.name)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const pestoIngredients = shoppingListArray.filter((ingredient) =&amp;gt; {
  return ingredient.recipe.includes('pesto')
})

pestoIngredients.forEach((ingredient) =&amp;gt; {
  console.log(ingredient.name)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  "Wrapping" it up
&lt;/h3&gt;

&lt;p&gt;As you can see from logging these to the console we successfully created a &lt;code&gt;shoppingListArray&lt;/code&gt; that didn't modify our original immutable recipe arrays, &lt;code&gt;pastaRecipeArray&lt;/code&gt; and &lt;code&gt;pestoRecipeArray&lt;/code&gt;. We then were able to mutably modify the &lt;code&gt;shoppingListArray&lt;/code&gt; in a destructive manner to add, delete, and replace ingredients to our liking. We also calculated how much we needed to spend before going to the store. Lastly, we were able to separate these ingredients back into their respective recipes, &lt;code&gt;pastaIngredients&lt;/code&gt; and &lt;code&gt;pestoIngredients&lt;/code&gt; in preparation for a brilliant meal. &lt;/p&gt;

&lt;p&gt;Well, what a delicious &lt;strong&gt;dish&lt;/strong&gt; that was. I hope you enjoyed it as much as I did.  Again, Mangia Mangia!&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
  </channel>
</rss>
