This comes from a DM that needs to be shared, warts and all…
The first step is always to be sure we understand the problem as it is presented. We need to know what we are given as data, and what our objective is.
We are given two arrays with elements in no particular order. The goal is to create a third array of only the items found in both lists.
That describes the data and the objective. Even in a wordy narrative we can still boil it down to something clear and concise. Make that the first step: Study the problem.
const arr1 = [1, 3, 5, 7, 8, 9, 10] const arr2 = [2, 3, 4, 6, 8, 9, 11] const same = arr1.filter(x => arr2.includes(x)) console.log(same) // [3, 8, 9]
In that justCoolStuff thread you can see how this was done using a for loop, which is actually where I would start. Build a loop algorithm that works, then study it to determine if it can be refactored with an iterator (or as above, with two iterators).
To repeat, start with naïve code. That is not derogatory, but foundational. Don’t try to write elegant solutions out of the gate. Write basic code along the lines of what you want each statement to do.
const same = [] for (let x of arr1) { for (let y of arr2) { if (x === y) { same.push(x) } } }
That is the code to write in the beginning of working toward a solution. It is basic, imperative, and easy to read. All the logic is there to see, and it works. We could stop there.
The only reason to refactor would be if we are writing an expressive model, as opposed to imperative. The above is a step by step algorithm, where the earlier one is an expression. Expressional code tends to abstract away some of the logic so, we don’t read it, we assume it (given the promise made by the language).
Our example above uses numbers which is generally quite easy to work with. It is simple code, yes? Now we can inject other challenges to the problem. How about arrays of strings? Well, on the surface, the above code works with no changes needed, but what if we want to know the words are spelled the same, regardless if they are capitalized, uppercased or lowercased? Now we need more logic.
if (x.toLowerCase() === y.toLowerCase()) { }
Bummer that we broke the program to work with numbers in the process since numbers don’t have a toLowerCase method. That means we need logic to confine the inputs to string arrays. You see how the code is growing along the line of our immediate needs?
Ideation is a critical step once we have a clear understanding of the problem. It is actually the second step. Thinking through possible solution steps. For the above problem we will know that we need two loops, one nested in the other so that we can compare every object in one array to every object in the other. So we build the loops, leaving blank lines where the code will go. but making sure we have all the syntax correct on our loop structures.
for (let x of arr1) { for (let y of arr2) { // conditional code } }
That’s what I call, ‘sketching’. Ideate and sketch. Play with the ideas, even on paper.
Now for a real challenge, mutating the arrays. Let’s say we want all the matching values in each array converted to uppercase. Can we use the above loop structure?
Trick question, the answer is, no. The for of loop is read-only. In order to mutate the arrays we need to use an indexed loop.
for (let i = 0; i < arr1.length; i++) { for (let j = 0; j < arr2.length; j++) { } }
Our logic will be a little more complex, as a result.
if (arr1[i].toLowerCase() === arr2[j].toLowerCase()) { arr1[i] = arr1[i].toUpperCase() arr2[j] = arr1[i] same.push(arr1[i]) }
We still haven’t covered the logic that tests for strings, but the code will run as expected if we supply valid string arrays.
Is any of this helping you formulate in your mind how to approach a problem? Hopefully you see it as breaking the problem down into its component parts. Build each component part, and if possible even test it separately to iron out any weaknesses.
const arr1 = ['Cold', 'Hot', 'Warm', 'Tepid', 'Luke Warm'] const arr2 = ['cold', 'hot', 'luke warm', 'freezing', 'frozen'] const same = []
Now we run the code and poll the outputs…
> same <- ['COLD', 'HOT', 'LUKE WARM'] > arr1 <- ['COLD', 'HOT', 'Warm', 'Tepid', 'LUKE WARM'] > arr2 <- ['COLD', 'HOT', 'LUKE WARM', 'freezing', 'frozen']