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

时间:2022-12-06 07:40:25

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?

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

13 个解决方案

#1


42  

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:

从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>

Thanks wateriswet for bringing this to my attention. :)

感谢wateriswet引起我的注意。 :)

#2


41  

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

#3


9  

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

您可以在ES6 / ES2015中使用新的本机新Set(list)对象。 (即Babel,Typescript,或者幸运的是所有目标浏览器都支持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:

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

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

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

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

#4


8  

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:

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

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.

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

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

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

#5


6  

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

除了使用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]

#6


3  

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

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

change it to this:

把它改成这个:

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

    }
  }
  return false;
}

#7


2  

You should use indexOf instead of your isIn function:

您应该使用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


2  

And with some ES5 fun...

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

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

    return Object.keys(temp);
}

#9


1  

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.

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

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

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

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.

请注意,isin方法可以立即执行(甚至替换为)对indexOf的调用。

#10


1  

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.

然后我看看键而不是值。

#11


1  

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
}

#12


0  

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

根据接受的答案。这是CoffeeScript的等价物:

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

#13


0  

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.

欢呼。

#1


42  

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:

从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>

Thanks wateriswet for bringing this to my attention. :)

感谢wateriswet引起我的注意。 :)

#2


41  

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

#3


9  

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

您可以在ES6 / ES2015中使用新的本机新Set(list)对象。 (即Babel,Typescript,或者幸运的是所有目标浏览器都支持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:

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

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

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

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

#4


8  

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:

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

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.

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

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

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

#5


6  

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

除了使用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]

#6


3  

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

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

change it to this:

把它改成这个:

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

    }
  }
  return false;
}

#7


2  

You should use indexOf instead of your isIn function:

您应该使用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


2  

And with some ES5 fun...

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

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

    return Object.keys(temp);
}

#9


1  

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.

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

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

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

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.

请注意,isin方法可以立即执行(甚至替换为)对indexOf的调用。

#10


1  

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.

然后我看看键而不是值。

#11


1  

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
}

#12


0  

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

根据接受的答案。这是CoffeeScript的等价物:

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

#13


0  

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.

欢呼。