У меня есть массив чисел, которые я должен убедиться, что они уникальны. Я нашел фрагмент кода ниже в интернете, и он прекрасно работает, пока в массиве нет нуля. Я нашел этот другой скрипт здесь, в Переполнении стека, который выглядит почти так же, как и он, но он не дает сбоя.
Таким образом, ради того, чтобы помочь мне учиться, может ли кто-нибудь помочь мне определить, в чем проблема с прототипом скрипта?
Array.prototype.getUnique = function() {
var o = {}, a = [], i, e;
for (i = 0; e = this[i]; i++) {o[e] = 1};
for (e in o) {a.push (e)};
return a;
}
Больше ответов от дублирующего вопроса:
Подобный вопрос:
javascript
arrays
unique
Mottie
источник
источник
o
=object
,a
=array
,i
=index
иe
= ммм, что-то: PОтветы:
В JavaScript 1.6 / ECMAScript 5 вы можете использовать собственный
filter
метод Array следующим образом, чтобы получить массив с уникальными значениями:Собственный метод
filter
будет перебирать массив и оставлять только те записи, которые передают данную функцию обратного вызоваonlyUnique
.onlyUnique
проверяет, является ли данное значение первым Если нет, он должен быть дубликатом и не будет скопирован.Это решение работает без какой-либо дополнительной библиотеки, такой как jQuery или prototype.js.
Это работает и для массивов со смешанными типами значений.
Для старых браузеров (<ie9), которые не поддерживают собственные методы
filter
иindexOf
вы можете найти работу обходные в документации MDN для фильтра и IndexOf .Если вы хотите сохранить последнее вхождение значения, просто замените
indexOf
наlastIndexOf
.С ES6 это может быть сокращено до этого:
Спасибо Camilo Martin за подсказку в комментарии.
ES6 имеет собственный объект
Set
для хранения уникальных значений. Чтобы получить массив с уникальными значениями, вы можете сделать это:Конструктор объекта
Set
принимает итеративный объект, такой как Array, а оператор распространения...
преобразует набор обратно в Array. Спасибо Лукасу Лизе за подсказку в комментарии.источник
['a', 1, 'a', 2, '1']
вы получите['a', 1, 2]
. Но это не то, что я ожидал. Кстати, гораздо медленнее, очень относительный..filter((v,i,a)=>a.indexOf(v)==i)
(жирная стрелка обозначения).let unique_values = [...new Set(random_array)];
developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Обновленный ответ для ES6 / ES2015 : Используя Set , однострочное решение:
Который возвращается
Как предложил le_m , это также можно сократить с помощью оператора распространения , например
источник
Array.from(new Set([[1,2],[1,2],[1,2,3]]))
myArray.filter((v, i, a) => a.indexOf(v) === i);
?Set
объекты и добавлять вместо примитивных значений, он будет содержать уникальные ссылки на объекты. Таким образом, sets
inlet s = new Set([{Foo:"Bar"}, {Foo:"Bar"}]);
будет возвращать следующее:Set { { Foo: 'Bar' }, { Foo: 'Bar' } }
этоSet
уникальные ссылки на объекты, содержащие одинаковые значения. Если вы напишите,let o = {Foo:"Bar"};
а затем создадите набор с двумя ссылками, например, так:let s2 = new Set([o,o]);
s2 будетSet { { Foo: 'Bar' } }
new Set
трофейЯ понимаю, что на этот вопрос уже есть более 30 ответов. Но я сначала прочитал все существующие ответы и провел собственное исследование.
Я разделил все ответы на 4 возможных решения:
[...new Set( [1, 1, 2] )];
{ }
для предотвращения дублирования[ ]
filter + indexOf
Вот примеры кодов, найденных в ответах:
Используйте новую функцию ES6:
[...new Set( [1, 1, 2] )];
Используйте объект
{ }
для предотвращения дублированияИспользовать вспомогательный массив
[ ]
использование
filter + indexOf
И мне стало интересно, какой из них быстрее. Я сделал образец Google Sheet для тестирования функций. Примечание. ECMA 6 недоступен в Google Sheets, поэтому я не могу его протестировать.
Вот результат тестов:
Я ожидал увидеть, что код, использующий объект
{ }
, победит, потому что он использует хэш. Поэтому я рад, что тесты показали лучшие результаты для этого алгоритма в Chrome и IE. Спасибо @rab за код .источник
Вы также можете использовать underscore.js .
который вернется:
источник
array = [...new Set(array)]
Один лайнер, чистый JavaScript
С синтаксисом ES6
list = list.filter((x, i, a) => a.indexOf(x) == i)
С синтаксисом ES5
Совместимость браузера : IE9 +
источник
С тех пор я нашел хороший метод, который использует jQuery
Примечание. Этот код был взят из сообщения Уши Пола Айриша: я забыл отдать должное: P
источник
Самое короткое решение с ES6:
[...new Set( [1, 1, 2] )];
Или, если вы хотите изменить прототип Array (как в оригинальном вопросе):
EcmaScript 6 реализован только частично в современных браузерах (август 2015 г.), но Babel стала очень популярной для переноса ES6 (и даже ES7) обратно в ES5. Таким образом, вы можете написать код ES6 сегодня!
Если вам интересно, что это
...
значит, он называется оператором спреда . От MDN : «Оператор распространения позволяет расширять выражение в местах, где ожидаются несколько аргументов (для вызовов функций) или несколько элементов (для литералов массива)». Поскольку набор является итеративным (и может иметь только уникальные значения), оператор распространения будет расширять набор для заполнения массива.Ресурсы для изучения ES6:
источник
a = [...Set(a)]
но, во всяком случае, пока это только Firefox.require ( "core-js/fn/array/from" );
[...Set(['a', 1, 'a', 2, '1'])]
сгенерирует ошибку TypeError, так что все равно целесообразно сохранитьnew
:[...new Set(['a', 1, 'a', 2, '1'])]
Самое простое решение:
Или:
источник
Самый простой и быстрый (в Chrome) способ сделать это:
Просто просматривает каждый элемент в массиве, проверяет, есть ли этот элемент в списке, и, если это не так, нажимает на возвращаемый массив.
Согласно jsPerf, эта функция самая быстрая из тех, что я мог найти где угодно - не стесняйтесь добавлять свои собственные.
Непрототипная версия:
Сортировка
Когда также необходимо отсортировать массив, следующее является самым быстрым:
или не прототип:
Это также быстрее, чем описанный выше метод в большинстве браузеров без Chrome.
источник
unique
функции, имеет сложность O (n ^ 2), в то время как алгоритмgetUnique
O (n). Первый может быть быстрее для небольших наборов данных, но как вы можете спорить с математикой :) Вы можете убедиться, что последний быстрее, если вы запустите его на массиве, скажем, 1e5 уникальных элементовТОЛЬКО ЭФФЕКТИВНОСТЬ! этот код, вероятно, в 10 раз быстрее, чем все коды здесь *, работает во всех браузерах, а также имеет минимальное влияние на память .... и многое другое
если вам не нужно повторно использовать старый массив, btw, выполните другие необходимые операции, прежде чем преобразовать его в уникальный, здесь, вероятно, самый быстрый способ сделать это, также очень короткий.
тогда вы можете попробовать это
Я придумал эту функцию, читая эту статью ...
http://www.shamasis.net/2009/09/fast-algorithm-to-find-unique-items-in-javascript-array/
Мне не нравится цикл for. он имеет много параметров. Мне нравится цикл while--. while - самый быстрый цикл во всех браузерах, кроме того, который нам всем так нравится ... chrome.
Во всяком случае, я написал первую функцию, которая использует while. И да, это немного быстрее, чем функция, найденная в статье. Но недостаточно.
unique2()
Следующий шаг использовать современные JS.
Object.keys
я заменил другой цикл for на js1.7 Object.keys ... немного быстрее и короче (в chrome в 2 раза быстрее);). Недостаточно!.unique3()
,в этот момент я думал о том, что мне действительно нужно в МОЕЙ уникальной функции. мне не нужен старый массив, я хочу быструю функцию. так что я использовал 2 цикла + петли.
unique4()
Бесполезно говорить, что я был впечатлен.
хром: обычные 150 000 операций в секунду подскочили до 1 800 000 операций в секунду.
то есть: 80 000 операций / с против 3 500 000 операций / с
IOS: 18 000 операций / с против 170 000 операций / с
сафари: 80 000 оп / с против 6 000 000 оп / с
Доказательство http://jsperf.com/wgu или лучше использовать console.time ... microtime ... что угодно
unique5()
просто чтобы показать вам, что происходит, если вы хотите сохранить старый массив.Не используйте,
Array.prototype
если вы не знаете, что делаете. Я только что сделал много копий и прошлого. Используйте,Object.defineProperty(Array.prototype,...,writable:false,enumerable:false})
если вы хотите создать собственный prototype.example: https://stackoverflow.com/a/20463021/2450730Демо http://jsfiddle.net/46S7g/
ПРИМЕЧАНИЕ: ваш старый массив уничтожается / становится уникальным после этой операции.
Если вы не можете прочитать приведенный выше код, спросите, прочитайте книгу по javascript или вот несколько объяснений более короткого кода. https://stackoverflow.com/a/21353032/2450730
некоторые используют
indexOf
... не ... http://jsperf.com/dgfgghfghfghghgfhgfhfghfhgfhдля пустых массивов
источник
Многие из ответов здесь могут быть не полезны для начинающих. Если дедупликация массива затруднительна, они действительно будут знать о цепочке прототипов или даже jQuery?
В современных браузерах чистое и простое решение - хранить данные в наборе , который представляет собой список уникальных значений.
Это
Array.from
полезно для преобразования Set обратно в массив, чтобы у вас был легкий доступ ко всем удивительным методам (функциям), которые есть у массивов. Есть и другие способы сделать то же самое. Но вам может и не понадобитьсяArray.from
, поскольку в Set есть множество полезных функций, таких как forEach. .Если вам требуется поддержка старого Internet Explorer и, следовательно, вы не можете использовать Set, тогда простой способ - скопировать элементы в новый массив, предварительно проверив, находятся ли они уже в новом массиве.
Чтобы сделать это мгновенно повторно используемым, давайте поместим это в функцию.
Таким образом, чтобы избавиться от дубликатов, мы бы сейчас сделали это.
deduplicate(cars)
Часть становится вещью мы назвали результат , когда функция завершается.Просто передайте ему имя любого массива, который вам нравится.
источник
источник
push
использовали элемент в массиве вместо использованияconcat
? Я попытался использовать толчок, и это не удалось. Я ищу объяснение.[0,1,2,0,3,2,1,5].reduce((prev, cur) => ~prev.indexOf(cur) ? prev : prev.concat([cur]), []);
NaN
дружественнойМы можем сделать это, используя наборы ES6:
// Вывод будет
источник
Этот прототип
getUnique
не совсем корректен, потому что если у меня есть Array like:["1",1,2,3,4,1,"foo"]
он вернется["1","2","3","4"]
и"1"
будет строкой и1
является целым числом; они разные.Вот правильное решение:
с помощью:
Выше будет производить
["1",2,3,4,1,"foo"]
.источник
$foo = 'bar'
это PHP-способ объявления переменных. Это будет работать в javascript, но создаст неявный глобальный, и, как правило, не должно быть сделано.$foo
, что способ объявления переменных в javascript, хотя на самом делеvar foo
это так.Не расширяя Array.prototype (это считается плохой практикой) или используя jquery / underscore, вы можете просто создать
filter
массив.Сохраняя последнее вхождение:
или первое вхождение:
Ну, это всего лишь javascript ECMAScript 5+, что означает только IE9 +, но он хорош для разработки на нативном HTML / JS (приложение для Магазина Windows, Firefox OS, Sencha, Phonegap, Titanium, ...).
источник
filter
. На странице MDN есть реализация Internet Explorer, я имею в виду старые браузеры. Также: JS 1.6 относится только к js-движку Firefox, но правильно сказать, что это ECMAScript 5.магия
O (N) производительность ; мы предполагаем, что ваш массив находится в
a
иt={}
. Объяснение здесь (+ Jeppe impr.)Показать фрагмент кода
источник
in
оператор вне конструкции, кромеfor
цикла: P) - Спасибо - я ценю это и дам +2 к другим вашим хорошим ответам ,t
которая сохраняется после фильтрации ... ??источник
Если вы используете платформу Prototype, вам не нужно делать циклы 'for', вы можете использовать http://www.prototypejs.org/api/array/uniq следующим образом:
Который будет производить дубликат массива без дубликатов. Я наткнулся на ваш вопрос в поисках метода для подсчета различных записей массива, так что после
я использовал
и был мой простой результат. ps Извините, если я что-то неправильно набрал
редактировать: если вы хотите избежать неопределенных записей, вы можете добавить
раньше, вот так:
источник
Теперь с помощью наборов вы можете удалять дубликаты и преобразовывать их обратно в массив.
Другое решение заключается в использовании сортировки и фильтрации
источник
Это потому, что
0
это ложное значение в JavaScript.this[i]
будет ложным, если значение массива 0 или любое другое ложное значение.источник
источник
o
вместо просто a1
, хотя сравнение на равенство будет по-прежнему строковым (хотя из всех возможных равенств Javascript это не выглядит слишком необоснованным).У меня была немного другая проблема, когда мне нужно было удалить объекты с дублирующимися свойствами идентификатора из массива. это сработало.
источник
Самый простой ответ:
источник
Я не уверен, почему Габриэль Сильвейра написал такую функцию, но более простая форма, которая работает для меня так же хорошо и без минимизации:
или в CoffeeScript:
источник
Если у вас все в порядке с дополнительными зависимостями или у вас уже есть одна из библиотек в вашей кодовой базе, вы можете удалить дубликаты из массива с помощью LoDash (или Underscore).
Применение
Если у вас его нет в базе кода, установите его с помощью npm:
Затем используйте его следующим образом:
Вне:
источник
На это было дано много ответов, но это не отвечало моим конкретным потребностям.
Многие ответы таковы:
Но это не работает для массивов сложных объектов.
Скажем, у нас есть такой массив:
Если нам нужны объекты с уникальными именами, мы должны использовать
array.prototype.findIndex
вместоarray.prototype.indexOf
:источник
От Shamasis Бхаттачария блога «s (O (2n) временной сложности):
Из блога Пола Айриша : улучшение JQuery
.unique()
:источник
Поиск уникальных значений Array простым методом
источник
Похоже, мы потеряли ответ Рафаэля , который был принятым ответом в течение нескольких лет. Это было (по крайней мере, в 2017 году) самое эффективное решение, если у вас нет массива смешанного типа :
Если вы делаете есть массив смешанного типа, вы можете сериализовать хэш - ключ:
источник
Чтобы решить эту проблему с другой стороны, может быть полезно не иметь дубликатов при загрузке массива, как это делает объект Set , но он пока недоступен во всех браузерах. Это экономит память и более эффективно, если вам нужно много раз просматривать его содержимое.
Образец:
Дает тебе
set = [1,3,4,2]
источник