admin管理员组

文章数量:1160793

I have this code:

var ar = [10,7,8,3,4,7,6];

function isin(n,a){
  for (var i=0;i<a.length;i++){
    if (a[i]== n) {
      var b = true;
      return b;
    } else {
      var c = false;
      return c;
   }
  }
}

function unique(a){
  var arr = [];
  for (var i=0;i<a.length;i++){
    if (!isin(a[i],arr)){
      arr.push(a[i]);
    }
  }

 return arr;
}

alert(unique(ar));

In this code, I try to create new unique array (without duplicates) out of the original one. But I still get the original array! Where's my mistake?

I have this code:

var ar = [10,7,8,3,4,7,6];

function isin(n,a){
  for (var i=0;i<a.length;i++){
    if (a[i]== n) {
      var b = true;
      return b;
    } else {
      var c = false;
      return c;
   }
  }
}

function unique(a){
  var arr = [];
  for (var i=0;i<a.length;i++){
    if (!isin(a[i],arr)){
      arr.push(a[i]);
    }
  }

 return arr;
}

alert(unique(ar));

In this code, I try to create new unique array (without duplicates) out of the original one. But I still get the original array! Where's my mistake?

Share Improve this question edited May 10, 2013 at 14:47 Jonik 81.7k76 gold badges269 silver badges379 bronze badges asked Aug 4, 2011 at 10:53 DrStrangeLoveDrStrangeLove 11.5k16 gold badges62 silver badges72 bronze badges
Add a comment  | 

19 Answers 19

Reset to default 81

Or for those looking for a one-liner (simple and functional):

var a = ["1", "1", "2", "3", "3", "1"];
var unique = a.filter(function(item, i, ar){ return ar.indexOf(item) === i; });

Using a plain array and returning the keys of associative array (containing only the "unique" values from given array) is more efficient:

function ArrNoDupe(a) {
    var temp = {};
    for (var i = 0; i < a.length; i++)
        temp[a[i]] = true;
    var r = [];
    for (var k in temp)
        r.push(k);
    return r;
}

$(document).ready(function() {
    var arr = [10, 7, 8, 3, 4, 3, 7, 6];
    var noDupes = ArrNoDupe(arr);
    $("#before").html("Before: " + arr.join(", "));
    $("#after").html("After: " + noDupes.join(", "));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="before"></div>
<div id="after"></div>

Note: The function does not preserve the order of the items, so if this is important use different logic.

As of IE9 and on all other modern browsers (e.g. Chrome, Firefox) this can become even more efficient by using the Object.keys() method:

function ArrNoDupe(a) {
    var temp = {};
    for (var i = 0; i < a.length; i++)
        temp[a[i]] = true;
    return Object.keys(temp);
}

$(document).ready(function() {
    var arr = [10, 7, 8, 3, 4, 3, 7, 6];
    var noDupes = ArrNoDupe(arr);
    $("#before").html("Before: " + arr.join(", "));
    $("#after").html("After: " + noDupes.join(", "));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="before"></div>
<div id="after"></div>

Thanks wateriswet for bringing this to my attention. :)

You could use the new native new Set(list) object in ES6/ES2015. (i.e. Babel, Typescript, or those lucky enough that all target browsers support ES2015).

// I never use this, because it's an iterator, not an array
let s = new Set(list);

or, if you want to chain to array helpers use the new ... spread operator in ES6/ES2015 to spread it into an array:

const unique = (list) => {
  return [...new Set(list)];
}

You need an array to chain methods like sort():

const convertText = (textToConvert) => {
  let list = unique(textToConvert.split(/\r?\n/g))
    .sort() // this will error if using uniqueAsIterator() version...
    .filter(x => x != "NULL");
  return list;
}

In addition to usage of filter respond by Josh Mc, you can make it crazy shorter in es6 with arrow function utility;

const a = ["1", "1", "2", "3", "3", "1"];
let unique = a.filter((it, i, ar) => ar.indexOf(it) === i);
// unique = [1, 2, 3]

Edit: note the warning by Daniel. Considering that, and what the official docs say (below), maybe using this is not a great idea after all!


If you happen to use jQuery, its unique() function does this:

var ar = [1, 2, 1, 2, 2, 3];    
ar = $.unique(ar);
console.log(ar);  // [3, 2, 1] 

The documentation says:

Note that this only works on arrays of DOM elements, not strings or numbers.

...but when I tested this with jQuery 1.9.1, it does work for strings and numbers too. Anyway, double-check that it works, especially if using older jQuery.

Because your isin method returns true or false after examining the first element.

change it to this:

function isin(n,a){
  for (var i=0;i<a.length;i++){
    if (a[i]== n){
    return true;

    }
  }
  return false;
}

You should use indexOf instead of your isIn function:

function unique(a){
  var arr = [];
  for (var i=0;i<a.length;i++){
    if ( arr.indexOf(a[i]) == -1){
        arr.push(a[i]);
    }
}

And with some ES5 fun...

function uniqueArray(array) {
    var temp = array.reduce(function(previous, current) {
        previous[current] = true;
        return previous;
    }, {});

    return Object.keys(temp);
}

Where's my mistake??

Right here:

... else {
      var c = false;
      return c;
   }

This causes the isin function to false if n doesn't match the first element in the array. The loop-body will always return a value before progressing to the next element.

Remove the else-clause and move return false to the bottom of the method:

function isin(n,a){
    for (var i=0;i<a.length;i++) {
        if (a[i] == n)
            return true;

    return false;
}

Note that the isin method can be implemented immediately (or even replaced by) a call to indexOf.

The way I did it was to use the array "backwards", so when I push to it I use the key instead of the value, like this:

var arr = [];
$('input[type=checkbox]', SearchResults).each( function() {
    if( $(this).is(':checked') )
        arr[ $(this).data('client_id') ] = true;
}

Then I look at the keys rather than the values.

Based on the accepted answer. Here is a CoffeeScript equivalent:

unique = (a) ->
  temp = {}
  for i in [0...a.length]
    temp[a[i]] = true
  r = []
  for k of temp
    r.push(k)
  return r

I know I'm somewhat late to answer this. But none of the answers have what I would do. I like using splice for this sort of thing. Here's a really simple script that'll do exactly what you need:

function unique(originalArray){
    var ar = originalArray.slice(0);//Make a copy of the array and store it in ar
    var i = ar.length;
    while(i--){  //Iterate through the array
        if(ar.indexOf(ar[i],i+1)>-1){  //If the array has a duplicate
            ar.splice(i,1);  //Remove that element!
        }
    }
    return ar; //Return the new, more unique array
}

You can use the Spread Operator and take advantage of the uniqueness offered by Sets.

const ar = [10, 7, 8, 3, 4, 7, 6];
const arUnique = [...new Set(ar)];

I've done a similar search, I found this answer really good:

Unique values in an array [duplicate]

You can re-use those function on other code. This is also good approach where it is compatible with many browsers.

Cheer.

Simplest version I know: Array.from(new Set(duplicateArray))

Expanding on Jamiecs' answer above, here's an Array.prototype. of the same.

var arr = [1, 1, 1, 2, 5, 6, 4, 5 , 1];

Array.prototype.uniqueArr = function() {
var arr = [];
for (var i=0;i<this.length;i++) {
  if ( arr.indexOf(this[i]) == -1 ) {
    arr.push(this[i]);
  }
}
return arr
}

var arr = arr.uniqueArr();

console.log(arr);

Using Filter Function

const getUnique = (arr) => {
  return arr.filter((val, i, _self) => {
  return _self.indexOf(val) === i;
 });
}
let arr = [1,2,1,3,4,2];
console.log(getUnique(arr)); // [ 1, 2, 3, 4 ]

If you are okay with/already using lodash, then uniq function of Array is the one you are looking for.

_.uniq([2, 1, 2]);
// => [2, 1]

function ArrNoDupe(a) {
    var temp = {};
    for (var i = 0; i < a.length; i++)
        temp[a[i]] = true;
    var r = [];
    for (var k in temp)
        r.push(k);
    return r;
}

$(document).ready(function() {
    var arr = [10, 7, 8, 3, 4, 3, 7, 6];
    var noDupes = ArrNoDupe(arr);
    $("#before").html("Before: " + arr.join(", "));
    $("#after").html("After: " + noDupes.join(", "));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="before"></div>
<div id="after"></div>

本文标签: javascriptHow do I make an array with unique elements (ie remove duplicates)Stack Overflow