How to Get a Sequence in Order With No Duplicate Consecutive Items
Day 12! This one was a request. Implement the function uniqueInOrder which takes as argument a sequence and returns a list of items without any elements with the same value next to each other and preserving the original order of elements.
I found this is actually another Codewars challenge. You can find the challenge here
Disclaimer: There are MANY ways to solve this problem. These are a few answers that I wrote or find clever with explanations of why/how they work
TLDR: explanation of best solution at the bottom of the post and actual solutions at the bottom of each section
The Problem
Create a function that accepts a string or an array and returns a list of items without any elements with the same value next to each other and preserving the original order of elements.
Examples:
uniqueInOrder('AAAABBBCCDAABBB') // ['A', 'B', 'C', 'D', 'A', 'B'] uniqueInOrder('ABBCcAD') // ['A', 'B', 'C', 'c', 'A', 'D'] uniqueInOrder([1,2,2,3,3]) // [1,2,3] uniqueInOrder(['hello', 'Hello', 'Hello', 'Hello', 'dev', 'dev', 'world', 'World', 'dev', 'world']) // ['hello', 'Hello', 'dev', 'world', 'World', 'dev', 'world'] uniqueInOrder([1, 1, 2, 2, 3, 3, 1, 1, 1]) // [1,2,3,1]
Solution
Solution 1
create a variable for a final array
loop through input
if the current item doesn’t match the last one push it onto the final array otherwise continue the loop
after the loop return the final array
Solution 2
spread input into an array (in case it is a string)
filter by checking if the index before it was the same as the current item
Solution 1 - More Readable
Create a function that accepts and input
function uniqueInOrder(input) { //create a variable for a final array //loop through input //if the current item doesn’t match the last one push it onto the final array otherwise continue the loop //after the loop return the final array }
Create a variable for us to push everything into that will be the array we return at the end.
function uniqueInOrder(input) { let finalArray = [] //loop through input //if the current item doesn’t match the last one push it onto the final array otherwise continue the loop //after the loop return the final array }
use a for loop to loop through the array that was passed to the function.
function uniqueInOrder(input) { let finalArray = [] for (let i = 0; i < input.length; i++) { //if the current item doesn’t match the last one push it onto the final array otherwise continue the loop } //after the loop return the final array }
To see if we are on an item that we were just on we are going to check the finalArray. Since we are pushing everything to that as we go through if the last item in the array is the same as the current item then it is a duplicate consecutive. Otherwise it isn’t and we want to add it. You will notice we are checking finalArray.length -1 because we are checking the index and indexes are 0 indexed which means they start at 0 instead of 1. To get the last index we need to take 1 off the length because the index is always 1 lower than the length (length is not 0 indexed). If it is not a duplicate we are going to push the item onto the final array. This will put that item at the end of the final array.
function uniqueInOrder(input) { let finalArray = [] for (let i = 0; i < input.length; i++) { if (input[i] != finalArray[finalArray.length - 1]) { finalArray.push(input[i]) } } //after the loop return the final array }
Now we just need to return the final array we have been pushing everything into
function uniqueInOrder(input) { let finalArray = [] for (let i = 0; i < input.length; i++) { if (input[i] != finalArray[finalArray.length - 1]) { finalArray.push(input[i]) } } return finalArray }
Solution 2 - Less Lines of Code and More Performant
Again we are going to create a function that accepts and input
function uniqueInOrder(input){ //spread input into an array (in case it is a string) //filter by checking if the index before it was the same as the current item }
function uniqueInOrder(input){ [input] }
Then we are going to filter the array by checking if the index before the current item is the same as it. If it is it will filter it out.
function uniqueInOrder(input){ return [input].filter((item, index) => item !== input[index - 1]) }
Conclusion
Even though solution 2 is more performant I think solution 1 is easier to read. Although solution 2 isn’t too hard to read. If you are interested in the performance tested on jsbench here are my results using the test cases above.
I hope you had fun with this one! Please leave your repo links to your form in the comments section. Also let me know if you like the multi day challenges or really hate them! If you have any challenge you would like to see done also leave that in the comments below you may see it come up! If you would like to get the challenge emailed to you every day in morning and a notification when the solution is posted subscribe below.