Vanilla javascript for duplicates not working

Hi,

I had seen but was not able to understand functions like reduce,filter etc, now as i need to use a way to filter out duplicates from an array i am trying to make a vanilla JS function, i seem to be successful for 2 duplicates values in a row like - like here -


[3,3,1,1,5];

but not with  3 in a row like [3,3,3,1,1,1,5];

Here the code returns 3 and 1 twice …

My logic is to compare each value other then itself and splice it out if it matches any other value , kindly guide me here …Thanks


 var test = [3,3,3,1,1,1,5];   
              for(var i = 0; i < test.length;i++){
                  for(var j = i+1; j < test.length;j++){
                     if(test[i] === test[j]){
                         test.splice(i,1);
                      }
                  } 
               }
              
 console.log(test);

Consider creating an empty array - perhaps call it output. When iterating over test, check to see if output contains the current value from test. If not, push value to the output array. Also consider looking into Set.

the problem in your implementation is .splice. It changes the array you are iterating over, so when you move everything over one position to the left after .splicing, the next round, you’ll skip an element. Using an empty array for output as suggested by @0x0936 or learning about .filter will be really helpful.

1 Like

@0x0936 - Thanks, i am sorry , i mean the process of finding duplicates in two arrays and finding duplicates in one array itself by creating 2 loops is it not same, i am really confused here …

@forkerino - thanks, i really want learn it using loops not filter, i have tried a lot of ways and it seems not to work with plain javascript …

Well, you can solve it with just a loop (although .filter is plain javascript, too and you should definitely learn it!), you’ll only need one loop, not a nested loop and you will need to check if the current value is the first occurrence of that value in the array. To check that, you can use something like .indexOf().

But i am really confused with indexOf , can i not get it done with out it , is there no way to do it with for, if or other such basic foundation stuff …

I guess there is, but it becomes a lot more complicated (harder to write, definitely harder to read and harder to debug). If you are confused by a certain concept (indexOf, filter, etc), it is better to try and use it and see how it works, ask questions if needed, than to find ways to work around it. I’m not saying it isn’t possible without, it certainly is, but if you don’t learn new concepts, you’ll get stuck pretty soon. I am challenging you to learn about something you don’t know yet!

splice changes the array size and affects array indexes - using splice in the loop body reindexes the array so any computation based on index values or the array size before the splice is no longer valid

to see this put console.log in the loop

console.log(`i ${i} j ${j} test [${test}]`)

more importantly you should step back and think about the problem you are tying to solve before writing any code - for example what about this array [3, 3, 1, 1, 3, 5]

it is crucial to have a complete statement of the problem as well as some test cases before attempting a solution - also try to write up a working solution using everyday language with pen and paper before expressing the solution in code

1 Like

@ppc = thanks , i am aware of the use of indexof etc and i have been trying since some time today, but my objective of using only if,else,for loop to get it done is not fructifying and i have not yet seen any thing like that on forum so far as well…so may be its impossible in JS ?

1 Like

Like I said earlier, it is definitely possible, but you will need another array to store the results, as .splice messes up the indexing inside loops.

@forkerino @camperextraordinaire - Now i did something and repeated the code 3 time , now this code works for any combination and removes duplicates , but how do i remove these 3 repeats - @camperextraordinaire yet to peep at solution



     var test = [3,3,3,3,3,1,1,1,5,7,7,7,6,3,3,3,3,3,3,3,7,3,9,23,12,12,12,12,12];
        

              for(var i = 0; i < test.length;i++){
                  for(var j = i+1; j < test.length;j++){
                     if(test[i] === test[j]){
                       
                         test.splice(i,1);
                      
                      }
                  } 
               }
 

 
 for(var i = 0; i < test.length;i++){
                  for(var j = i+1; j < test.length;j++){
                     if(test[i] === test[j]){
                        
                         test.splice(i,1);
                       
                      }
                  } 
               }

for(var i = 0; i < test.length;i++){
                  for(var j = i+1; j < test.length;j++){
                     if(test[i] === test[j]){
                        
                         test.splice(i,1);
                       
                      }
                  } 
               }

console.log(test);

you remove the repeats by pushing the values that are not encountered before to a result array instead of using .splice. That way you only need one nested loop.

I see - so you only want to use basic constructs and not built-in functions - couple comments here

the built-in objects and methods are plain js - array methods go with the array object - if something is possible with built-in functions it cannot be impossible in js

splice is an array function with an implicit loop - are you allowing an exception for its use?

also your use of splice suggests the problem is to remove duplicates from an array in-place without using extra storage - is that right?

1 Like

@camperextraordinaire @forkerino - I have not yet looked at the solutions but took your suggestions which where -

1)Why i am using splice if i am so much against indexOf etc

2)I can use a new array and push values that are unique …

So i came up with this -

Now if the values match in the for loop , i simply set that value to null, then just outside the loop push non null in new array , simple :slight_smile: , thanks for your help here , will need more for sure with my limited abilities in coding …


 var test = [3,3,3,3,3,1,1,1,5,7,7,7,6,3,3,3,3,3,3,3,7,3,9,23,12,12,12,12,12];
        var test1 = [];
            
              for(var i = 0; i < test.length;i++){
                  for(var j = i+1; j < test.length;j++){
                     if(test[i] === test[j]){
                         test[i] = null;
                        }
                      
                  }
                 if(test[i] !== null){
                    test1.push(test[i]);
                 }
                }
 
console.log(test1);

congrats on getting a working solution. I would like to repeat my advice to start using concepts that you don’t yet know or are uncomfortable about, otherwise you will not grow as a developer as fast as you can. Try to rewrite this simple algorithm using a .filter() and .indexOf(), it will be worth your time and effort, because it will save you a LOT of time in the future if you start learning these things now.

1 Like

@forkerino -thanks , i will surely do after i have my developers certificate, ready made functions rarely help one’s logical ability and we tend to forget what to do when put in same situations again , while logically solving problems with bare minimum help much more …

such little time - so much to code

both have merit - learn the expressive power of higher-level constructs - and understand the underlying basic operations

1 Like

Like @ppc said there is benefit in understanding both, but don’t postpone a big part of a language just because you don’t understand it, because that is a recipe for 1- overcomplicating things, 2- not getting the benefit of learning how to use more advanced features that are extremely important in the job market and 3- writing code that is hard to read and hard to debug. You can write dozens of for loops and if/else statements, but at some point you have to do something that makes you a little uncomfortable so you can take the next step. Consider the same idea but with a .filter() and an .indexOf() (don’t read if you haven’t tried writing it yourself):

test.filter(function(val, index){
  return index === test.indexOf(val);
});

or with an arrow function:

test.filter((val, index) => test.indexOf(val) === index);

It is so much cleaner and easier to read than using the loops, that I would consider the for loops a code smell in this case.

1 Like

Set example

var input = [1, 1, 2, 2, 3, 4]
var set = new Set(input)
var output = Array.from(set)

For…Of example (useful when you don’t need to care about the index)

var input = [1, 1, 2, 2, 3, 4]
var output = []
for (var n of input) {
  if (!output.includes(n)) {
   output.push(n)
  }
}

Regex example (unconventional - for amusement only)

var arr = [1, 1, 3, 3, 3, 4, 5,]
arr.sort((a, b) => a - b)
  .join('')
  .replace(/(\d)\1+/g, '$1')
  .split('')
  .map(Number)
2 Likes