109

I have JS array with strings, for example:

var strArray = [ "q", "w", "w", "e", "i", "u", "r"];

I need to compare for duplicate strings inside array, and if duplicate string exists, there should be alert box pointing to that string.

I was trying to compare it with for loop, but I don't know how to write code so that array checks its own strings for duplicates, without already pre-determined string to compare.

Penny Liu
  • 15,447
  • 5
  • 79
  • 98
Bengall
  • 1,267
  • 2
  • 9
  • 13
  • Consecutive duplicates, or duplicates of any sort? If you threw another 'q' in there at the end, should that count as a duplicate or not? – kshetline Mar 11 '18 at 00:19
  • Duplicates of any sort. It can be in in the middle of the array, or at the end of the array, or any other combination. – Bengall Mar 11 '18 at 00:24
  • In my tests, the **fastest** method is [**this one**](https://stackoverflow.com/a/56094764/8112776). – ashleedawg Aug 29 '20 at 21:09
  • @ashleedawg in what tests? The array [2,3,4,1,1, ...] where the dots are an array of many elements, should run significantly slower than the hash map as it needs to pass through the full array 4 times in the example above, while a map of values and using `in` would only go through the array once – Gabriel Petersson Jun 13 '22 at 12:10

13 Answers13

169

The findDuplicates function (below) compares index of all items in array with index of first occurrence of same item. If indexes are not same returns it as duplicate.

let strArray = [ "q", "w", "w", "w", "e", "i", "i", "u", "r"];
let findDuplicates = arr => arr.filter((item, index) => arr.indexOf(item) !== index)

console.log(findDuplicates(strArray)) // All duplicates
console.log([...new Set(findDuplicates(strArray))]) // Unique duplicates
João Pimentel Ferreira
  • 14,289
  • 10
  • 80
  • 109
Mike Ezzati
  • 2,968
  • 1
  • 23
  • 34
  • 1
    Note the [time complexity](https://www.bigocheatsheet.com/) here. Looping inside of a loop: O(n^2). Doesn't really matter unless the array is MASSIVE or you're doing this MANY times on a server. But when it matters, it really matters. [`kshetline's` answer](https://stackoverflow.com/a/49215482/99717) performs better at O(n). BUT, that answer trades time for space (the object map), so watch out for that too :) – Hawkeye Parker Jan 19 '23 at 18:06
149

Using ES6 features

  • Because each value in the Set has to be unique, the value equality will be checked.

function checkIfDuplicateExists(arr) {
    return new Set(arr).size !== arr.length
}
  
var arr = ["a", "a", "b", "c"];
var arr1 = ["a", "b", "c"];

console.log(checkIfDuplicateExists(arr)); // true
console.log(checkIfDuplicateExists(arr1)); // false
xinthose
  • 3,213
  • 3
  • 40
  • 59
Kamil Naja
  • 6,267
  • 6
  • 33
  • 47
29

    var strArray = [ "q", "w", "w", "e", "i", "u", "r", "q"];
    var alreadySeen = {};
  
    strArray.forEach(function(str) {
      if (alreadySeen[str])
        console.log(str);
      else
        alreadySeen[str] = true;
    });

I added another duplicate in there from your original just to show it would find a non-consecutive duplicate.

Updated version with arrow function:

const strArray = [ "q", "w", "w", "e", "i", "u", "r", "q"];
const alreadySeen = {};
  
strArray.forEach(str => alreadySeen[str] ? console.log(str) : alreadySeen[str] = true);
kshetline
  • 12,547
  • 4
  • 37
  • 73
  • This solution works great, too! Thanks. Shame I can't accept (green checkmark) your answer also. – Bengall Mar 11 '18 at 00:58
  • Nice one. This particular logic easily allows for "Any" behavior (that is, I can short-circuit the loop when I find that there is any duplicate). – wildbagel Aug 28 '20 at 16:19
  • Can I clarify something please? Does the above expression `alreadySeen[str] = true` just add that `str` item to the `alreadySeen` array? Is it the same as `alreadySeen.push(str)`? – Ben Clarke Oct 25 '21 at 08:04
  • 1
    @BenClarke, no, because a push word add `str` as an element of the array, whereas `alreadySeen[str] = true` adds `str` as an index of the array, using the array as a hash table. A `Set` object could be used here instead, perhaps with greater clarity. – kshetline Oct 25 '21 at 08:46
  • @kshetline Ok thank you for clarifying. That's a bit too advanced for me though :) Is that method called anything in particular? I'd like to learn more about it – Ben Clarke Oct 25 '21 at 14:13
  • It is considered bad practice to use arrays to store key-value pairs in Javascript (See https://stackoverflow.com/a/874237/5263954). Better to use `alreadySeen = {}` instead. – René K Jun 30 '22 at 22:03
  • @René K, good point. – kshetline Jul 01 '22 at 23:17
10

Using some function on arrays: If any item in the array has an index number from the beginning is not equals to index number from the end, then this item exists in the array more than once.

// vanilla js
function hasDuplicates(arr) {
    return arr.some( function(item) {
        return arr.indexOf(item) !== arr.lastIndexOf(item);
    });
}
Nicolas Bouvrette
  • 4,295
  • 1
  • 39
  • 53
Halil Azyikmis
  • 139
  • 1
  • 5
  • Hi, your function is what I need (return only a boolean) but I don't know ES6, can you write it in "simple" javascript please ? – Eve Jul 16 '19 at 14:11
10

You could take a Set and filter to the values that have already been seen.

var array = ["q", "w", "w", "e", "i", "u", "r"],
    seen = array.filter((s => v => s.has(v) || !s.add(v))(new Set));

console.log(seen);
Ry-
  • 218,210
  • 55
  • 464
  • 476
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
2

function hasDuplicates(arr) {
    var counts = [];

    for (var i = 0; i <= arr.length; i++) {
        if (counts[arr[i]] === undefined) {
            counts[arr[i]] = 1;
        } else {
            return true;
        }
    }
    return false;
}

// [...]

var arr = [1, 1, 2, 3, 4];

if (hasDuplicates(arr)) {
  alert('Error: you have duplicates values !')
}

Simple Javascript (if you don't know ES6)

function hasDuplicates(arr) {
    var counts = [];

    for (var i = 0; i <= arr.length; i++) {
        if (counts[arr[i]] === undefined) {
            counts[arr[i]] = 1;
        } else {
            return true;
        }
    }
    return false;
}

// [...]

var arr = [1, 1, 2, 3, 4];

if (hasDuplicates(arr)) {
  alert('Error: you have duplicates values !')
}
nircraft
  • 8,242
  • 5
  • 30
  • 46
Eve
  • 776
  • 2
  • 11
  • 32
2
function hasDuplicateString(strings: string[]): boolean {
    const table: { [key: string]: boolean} = {}
    for (let string of strings) {
        if (string in table) return true;
        table[string] = true;
    }
    return false
}


Here the in operator is generally considered to be an 0(1) time lookup, since it's a hash table lookup.

J.E.C.
  • 2,616
  • 2
  • 18
  • 21
1
   var elems = ['f', 'a','b','f', 'c','d','e','f','c'];

    elems.sort();

    elems.forEach(function (value, index, arr){

        let first_index = arr.indexOf(value);
        let last_index = arr.lastIndexOf(value);

         if(first_index !== last_index){

         console.log('Duplicate item in array ' + value);

         }else{

         console.log('unique items in array ' + value);

         }

    });
Naveed Ali
  • 361
  • 3
  • 12
1

You have to create an empty array then check each element of the given array if the new array already has the element it will alert you. Something like this.

  var strArray = [ "q", "w", "w", "e", "i", "u", "r"];
  let newArray =[];
  function check(arr){
  for(let elements of arr){
  if(newArray.includes(elements)){
  alert(elements)
  }
 else{
 newArray.push(elements);
 }
 }
 return newArray.sort();
  }
check(strArray);
0

Use object keys for good performance when you work with a big array (in that case, loop for each element and loop again to check duplicate will be very slowly).

var strArray = ["q", "w", "w", "e", "i", "u", "r"];

var counting = {};
strArray.forEach(function (str) {
    counting[str] = (counting[str] || 0) + 1;
});

if (Object.keys(counting).length !== strArray.length) {
    console.log("Has duplicates");

    var str;
    for (str in counting) {
        if (counting.hasOwnProperty(str)) {
            if (counting[str] > 1) {
                console.log(str + " appears " + counting[str] + " times");
            }
        }
    }
}
Văn Quyết
  • 2,384
  • 14
  • 29
0

This is the simplest solution I guess :

function diffArray(arr1, arr2) {
  return arr1
    .concat(arr2)
    .filter(item => !arr1.includes(item) || !arr2.includes(item));
}
0
 const isDuplicate = (str) =>{
   return new Set(str.split("")).size === str.length;
}
Abdullah Ismail
  • 415
  • 5
  • 6
  • 1
    Can you explain *why* this works? Since this question is rather old, it's a good idea to clearly articulate why it is useful. – Hazel へいぜる Oct 08 '21 at 21:37
  • The above method is a predicate method which means is only returning boolean value. Since set take only unique value, I split the string to array of character then I parse the array of character to the set constructor for removing any duplicate character. Which mean if duplicate exist in the character array, the set will contain on the unique ones, after that I compare the length of the original string against the set size. If the length are the same it means no duplicate else it means there is. – Abdullah Ismail Oct 10 '21 at 07:00
-1

You could use reduce:

const arr = ["q", "w", "w", "e", "i", "u", "r"]
arr.reduce((acc, cur) => { 
  if(acc[cur]) {
    acc.duplicates.push(cur)
  } else {
    acc[cur] = true //anything could go here
  }
}, { duplicates: [] })

Result would look like this:

{ ...Non Duplicate Values, duplicates: ["w"] }

That way you can do whatever you want with the duplicate values!

Taylor Austin
  • 5,407
  • 15
  • 58
  • 103