85

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
  • 11,885
  • 5
  • 66
  • 81
Bengall
  • 991
  • 1
  • 6
  • 12
  • 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

13 Answers13

140

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", "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
ashleedawg
  • 18,752
  • 7
  • 68
  • 96
Mike Ezzati
  • 2,608
  • 1
  • 22
  • 32
  • 16
    This doesn't return a unique array, duplicates will be included more than once if they're duplicated more than once in the array. `xxxyyyxxx` for example. – Zee Jun 07 '19 at 04:35
113

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
  • 2,529
  • 2
  • 35
  • 51
Kamil Naja
  • 5,402
  • 5
  • 30
  • 44
18

    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);
René K
  • 193
  • 3
  • 14
kshetline
  • 10,720
  • 4
  • 28
  • 57
  • 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
  • @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
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-
  • 209,133
  • 54
  • 439
  • 449
Nina Scholz
  • 351,820
  • 24
  • 303
  • 358
6

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
  • 3,228
  • 1
  • 30
  • 44
  • 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
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
  • 7,430
  • 5
  • 28
  • 44
Eve
  • 706
  • 1
  • 9
  • 27
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
  • 333
  • 3
  • 11
1
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.
  • 1,458
  • 1
  • 15
  • 17
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,028
  • 12
  • 28
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;
}
  • 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. – Taco タコス 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
0

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);
-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
  • 4,328
  • 11
  • 49
  • 90