Vanilla javascript for duplicates not working

Vanilla javascript for duplicates not working
0

#1

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);

#2

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.


#3

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.


#4

@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 …


#5

@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 …


#6

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().


#7

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 …


#8

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!


#9

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


#10

@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 ?


#11

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.


#12

You wanted a solution using 2 for loops and no indexOf function and no filter funtion? My solution below is identical to what @0x0936 explained to you in an earlier post above. The only difference is, in my solution, I called the output array noDuplicates instead of output.

  var test = [3,3,3,1,1,1,5];   
  var noDuplicates = []; // empty array to store only non-duplicates
  for(var testIdx = 0; testIdx < test.length; testIdx++) {
    var foundDuplicate = false; // assume current test array value is not a duplicate
    for(var noDupIdx = 0; noDupIdx < noDuplicates.length; noDupIdx++) {
      if(test[testIdx] === noDuplicates[noDupIdx]){
        foundDuplicate = true; // found a duplicate, so break out of inner for loop
        break;
      }
    } 
    if (foundDuplicate === false) {
      noDuplicates.push(test[testIdx]); // since could not find duplicate add to final array
    }
  }
              
 console.log(noDuplicates);

#13

@forkerino @RandellDawson - 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 - @RandellDawson 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);

#14

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.


#15

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?


#16

See @forkerino’s previous advice to you in a previous post.

Since your splice is moving everything over one position after the splice, you need change your i variable so you do not skip the next element. On the very next line after your splice, you can do

i -= 1;  // decrement i by one to offset splice effect

This will allow you to only use your original code with the only side-effect being the values are not in their original order:

  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);
        i -= 1;
      }
    } 
  }

console.log(test); // [ 1, 5, 6, 7, 3, 9, 23, 12 ]

Using spice for a solution in this way for large arrays is horribly inefficient though. What seems like a simple function and fairly short code is misleading, because behind the scenes, splice is having to rearrange the array indexes (more looping you do not see) to account for the missing value(s).

You really should learn how to use filter and indexOf to solve these types of problems.


#17

@RandellDawson @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);

#18

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.


#19

@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 …


#20

such little time - so much to code

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