如何使用唯一元素创建数组(即删除重复项)?

时间:2011-08-04 10:53:03

标签: javascript arrays

我有这段代码:

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

在这段代码中,我尝试从原始数组中创建新的唯一数组(没有重复数组)。 但我仍然得到原始阵列!哪里是我的错?

16 个答案:

答案 0 :(得分:65)

或者那些寻找单线程(简单且功能齐全)的人:

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

答案 1 :(得分:47)

使用普通数组并返回关联数组的键(仅包含给定数组中的“唯一”值)更有效:

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>

注意:该功能不保留项目的顺序,因此如果这很重要,请使用不同的逻辑。

从IE9和所有其他现代浏览器(例如Chrome,Firefox)开始,使用Object.keys()方法可以提高效率:

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>

感谢wateriswet bringing this to my attention。 :)

答案 2 :(得分:15)

您可以使用新的原生new Set(list) object in ES6/ES2015。 (即Babel,Typescript,或者幸运的是所有目标浏览器都支持ES2015)。

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

或者,如果您想链接到数组助手,请使用ES6 / ES2015中新的...扩展运算符将其扩展到数组中:

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

您需要一个数组来链接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;
}

答案 3 :(得分:9)

除了使用Josh Mc的过滤器响应之外,你还可以使用箭头功能实用程序在es6中缩短它的速度;

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

答案 4 :(得分:8)

修改:注意warning by Daniel。考虑到这一点,以及官方文档的说法(下文),也许使用它毕竟不是一个好主意!


如果你碰巧使用jQuery,它的unique() function会这样做:

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

文档说:

  

请注意,这仅适用于DOM元素的数组,而不适用于字符串或   号。

...但是当我使用jQuery 1.9.1进行测试时,它 也适用于字符串和数字。无论如何,仔细检查它是否有效,特别是如果使用旧的jQuery。

答案 5 :(得分:3)

因为在检查第一个元素后,isin方法返回true或false。

将其更改为:

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

    }
  }
  return false;
}

答案 6 :(得分:3)

有一些ES5的乐趣......

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

    return Object.keys(temp);
}

答案 7 :(得分:2)

您应该使用indexOf而不是isIn函数:

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

答案 8 :(得分:1)

  

哪里是我的错误?

就在这里:

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

如果isin数组中的第一个元素不匹配,则会导致n函数为false。在进入下一个元素之前,循环体将始终返回一个值。

删除else子句并将return false移到方法的底部:

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

    return false;
}

请注意,isin方法可以立即(或甚至替换为)indexOf调用实施。

答案 9 :(得分:1)

我这样做的方法是使用“向后”的数组,所以当我按下它时,我使用键而不是值,如下所示:

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

然后我看着键而不是值。

答案 10 :(得分:1)

我知道我有点迟到回答这个问题。但没有一个答案符合我的要求。我喜欢使用拼接来做这种事情。这是一个非常简单的脚本,可以完全满足您的需求:

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
}

答案 11 :(得分:0)

基于accepted answer。这是CoffeeScript的等价物:

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

答案 12 :(得分:0)

我做了类似的搜索,我发现这个答案非常好:

Unique values in an array [duplicate]

您可以在其他代码上重复使用这些功能。 这也是与许多浏览器兼容的好方法。

欢呼。

答案 13 :(得分:0)

我知道的最简单版本:Array.from(new Set(duplicateArray))

答案 14 :(得分:0)

扩展上面的Jamiecs'答案,这里是Array.prototype.的答案。

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

答案 15 :(得分:0)

使用过滤器功能

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 ]