Javascript 如何制作具有唯一元素的数组(即删除重复项)?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6940103/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 23:52:00  来源:igfitidea点击:

How do I make an array with unique elements (i.e. remove duplicates)?

javascriptarrays

提问by DrStrangeLove

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?

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

回答by Josh Mc

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

回答by Shadow Wizard is Ear For You

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引起我的注意。:)

回答by yzorg

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

您可以new Set(list)在 ES6/ES2015 中使用新的原生对象。(即 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 中的新扩展运算符将其扩展为数组:

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

回答by Burak Tokak

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]

回答by Jonik

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!

编辑:注意Daniel警告。考虑到这一点,以及官方文档所说的(如下),也许使用它毕竟不是一个好主意!



If you happen to use jQuery, its unique()functiondoes 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 doeswork for strings and numbers too. Anyway, double-check that it works, especially if using older jQuery.

...但是当我用 jQuery 1.9.1 测试它时,它适用于字符串和数字。无论如何,请仔细检查它是否有效,尤其是在使用较旧的 jQuery 时。

回答by Jamiec

Because your isinmethod 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;
}

回答by theGecko

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

回答by F-A

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

回答by aioobe

Where's my mistake??

我的错在哪里??

Right here:

就在这儿:

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

This causes the isinfunction to false if ndoesn't match the firstelement in the array. The loop-body will always return a value before progressing to the next element.

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

Remove the else-clause and move return falseto 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 isinmethod can be implemented immediately (or even replaced by) a call to indexOf.

请注意,该isin方法可以立即实现(甚至替换为)对 的调用indexOf

回答by david_nash

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.

然后我查看键而不是值。