Как создать массив с уникальными элементами (например, удалить дубликаты)?
У меня есть этот код:
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));
В этом коде я пытаюсь создать новый уникальный массив (без дубликатов) из исходного.
Но я все еще получаю исходный массив! Где моя ошибка?
Ответы
Ответ 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>
Ответ 2
Или для тех, кто ищет однострочный (простой и функциональный):
var a = ["1", "1", "2", "3", "3", "1"];
var unique = a.filter(function(item, i, ar){ return ar.indexOf(item) === i; });
Ответ 3
Изменить: обратите внимание на предупреждение Daniel. Учитывая это и то, что говорят официальные документы (см. Ниже), возможно, использование этого не является отличной идеей!
Если вы используете jQuery, его unique()
функция делает следующее:
var ar = [1, 2, 1, 2, 2, 3];
ar = $.unique(ar);
console.log(ar); // [3, 2, 1]
В документации написано:
Обратите внимание, что это работает только с массивами элементов DOM, а не строк или числа.
... но когда я тестировал это с помощью jQuery 1.9.1, он тоже работает для строк и чисел. В любом случае, дважды проверьте, что он работает, особенно если используется старый jQuery.
Ответ 4
Вы можете использовать новый родной new Set(list)
объект в ES6/ES2015. (т.е. Babel, Typescript, или тех, кому повезло, что все целевые браузеры поддерживают ES2015).
// I never use this, because it 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;
}
Ответ 5
В дополнение к использованию фильтра отвечает Джош Мак, вы можете сделать его сумасшедшим короче в 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
Поскольку ваш метод isin
возвращает true или false после проверки первого элемента.
измените его на это:
function isin(n,a){
for (var i=0;i<a.length;i++){
if (a[i]== n){
return true;
}
}
return false;
}
Ответ 7
Вы должны использовать 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
Где моя ошибка??
Прямо здесь:
... else {
var c = false;
return c;
}
Это приводит к тому, что функция isin
имеет значение false, если n
не соответствует первому элементу массива. Тело цикла всегда возвращает значение перед переходом к следующему элементу.
Извлеките 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
То, как я это делал, это использовать массив "назад", поэтому, когда я нажимаю на него, я использую ключ вместо значения, например:
var arr = [];
$('input[type=checkbox]', SearchResults).each( function() {
if( $(this).is(':checked') )
arr[ $(this).data('client_id') ] = true;
}
Затем я смотрю на клавиши, а не на значения.
Ответ 10
И с некоторым удовольствием ES5...
function uniqueArray(array) {
var temp = array.reduce(function(previous, current) {
previous[current] = true;
return previous;
}, {});
return Object.keys(temp);
}
Ответ 11
Я знаю, что немного опоздал, чтобы ответить на этот вопрос. Но ни один из ответов не имеет того, что я сделал бы. Мне нравится использовать сращивание для такого рода вещей. Здесь действительно простой script, который будет делать именно то, что вам нужно:
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
В соответствии с принятым ответом . Вот эквивалент 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
Я сделал аналогичный поиск, я нашел этот ответ действительно хорошим:
Уникальные значения в массиве [duplicate]
Вы можете повторно использовать эту функцию для другого кода.
Это также хороший подход, когда он совместим со многими браузерами.
Cheer.