Получить все уникальные значения в массиве JavaScript (удалить дубликаты)
У меня есть массив чисел, которые я должен убедиться, что они уникальны. Я нашел фрагмент кода ниже в интернете, и он прекрасно работает, пока в массиве нет нуля. Я нашел этот другой скрипт здесь на SO, который выглядит почти так же, как и он, но он не дает сбоя.
Таким образом, ради того, чтобы помочь мне учиться, может ли кто-нибудь помочь мне определить, в чем проблема с прототипом скрипта?
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;
}
Больше ответов от дублирующего вопроса:
Подобный вопрос:
140 ответов
Простое решение, если вы хотите проверить уникальные значения в неопределенном количестве параметров с помощью es6.
function uniteUnique(arr, ...rest) {
const newArr = arr.concat(rest).flat()
return [...new Set(newArr)]
}
console.log(uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]))
console.log(uniteUnique([1, 2, 3], [5, 2, 1]))
Надеюсь, это будет кому-то полезно.
Современный расширяемый, быстрый, эффективный и легко читаемый подход с использованием библиотеки iter-ops :
import {pipe, distinct} from 'iter-ops';
const input = [1, 1, 2, 2, 2, 3]; // our data
const i = pipe(input, distinct()); // distinct iterable
console.log([...i]); //=> [1, 2, 3]
И если ваш ввод представляет собой массив объектов, вы просто предоставите ключевой селектор для
distinct
оператор.
Если у вас есть массив объектов, и вы хотите uniqueBy
функция, скажем, по полю id:
function uniqueBy(field, arr) {
return arr.reduce((acc, curr) => {
const exists = acc.find(v => v[field] === curr[field]);
return exists ? acc : acc.concat(curr);
}, [])
}
Использование фильтра и склейки
myArray.filter((el,i)=>![...myArray].splice(0,i).includes(el))
Использование Set с прототипом из
Array.from(new Set(myArray))
Использование Set с оператором распространения
[...new Set(myArray)]
(function() {
"use strict";
Array.prototype.unique = function unique() {
var self = this;
return self.filter(function(a) {
var that = this;
// console.log(that);
return !that[a] ? that[a] = true : false;
}, {});
}
var sampleArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var distinctArray = sampleArray.unique();
console.log(distinctArray);
})();
Here is the simple way to solve this problem...
Используйте это без использования какой-либо функции и временной сложности O(n)
function uni(arr){
var i = 0,uk = 0;
for (j = 1; j < arr.length; j++){
if(arr[i] != arr[j]){
uk++;
i = j;
}
}
return uk + 1;
}
Code:
function RemoveDuplicates(array) {
return array.filter(function (value, index, self) {
return self.indexOf(value) === index;
});
}
Usages:
var arr = ["a","a","b","c","d", "d"];
console.log(RemoveDuplicates(arr));
Result:
0: "a"
1: "b"
2: "c"
3: "d"
Используя mongoose, у меня был массив ObjectIds для работы.
У меня был массив / список идентификаторов объектов для работы, с которыми сначала нужно было установить строку, а после уникального набора изменить обратно на идентификаторы объектов.
Я бы сортировал массив, тогда все дубликаты - соседи. Затем пройдите по массиву и удалите все дубликаты.
function getUniques(array) {
var l = array.length
if(l > 1) {
// get a cloned copy and sort it
array = [...array].sort();
var i = 1, j = 0;
while(i < l) {
if(array[i] != array[j]) {
array[++j] = array[i];
}
i++;
}
array.length = j + 1;
}
return array;
}
Использование метода Array.prototype.includes() для удаления дубликатов:
(function() {
const array = [1, 1, 2, 2, 3, 5, 5, 2];
let uniqueValues = [];
array.map(num => {
if (Number.isInteger(num) && !uniqueValues.includes(num)) {
uniqueValues.push(num)
}
});
console.log(uniqueValues)
}());
Если порядок не важен, мы можем создать хеш и получить ключи для создания уникального массива.
var ar = [1,3,4,5,5,6,5,6,2,1];
var uarEle = {};
links.forEach(function(a){ uarEle[a] = 1; });
var uar = keys(uarEle)
uar будет иметь уникальные элементы массива.
Я использовал Array# lower для создания уникального Array#.
Array.prototype.unique = function() {
var object = this.reduce(function(h, v) {
h[v] = true;
return h;
}, {});
return Object.keys(object);
}
console.log(["a", "b", "c", "b", "c", "a", "b"].unique()); // => ["a", "b", "c"]
Вот еще один подход с использованием компараторов (я больше забочусь о чистоте кода, чем о производительности):
const list = [
{name: "Meier"},
{name: "Hans"},
{name: "Meier"},
]
const compare = (a, b) => a.name.localeCompare(b.name);
const uniqueNames = list.makeUnique(compare);
uniqueNames.pushIfAbsent({name: "Hans"}, compare);
Декларация прототипа:
declare global {
interface Array<T> {
pushIfAbsent(item: T, compare:(a:T, b:T)=>number): number;
}
interface Array<T> {
makeUnique(compare:(a:T, b:T)=>number): Array<T>;
}
}
Array.prototype.pushIfAbsent = function <T>(this:T[], item:T, compare:(a:T, b:T)=>number) {
if (!this.find(existing => compare(existing, item)===0)) {
return this.push(item)
} else {
return this.length;
}
}
Array.prototype.makeUnique = function <T>(this:T[], compare:(a:T, b:T)=>number) {
return this.filter((existing, index, self) => self.findIndex(item => compare(existing, item) == 0) == index);
}
Если вы хотите изменить его на месте (не создавая новый массив), вы можете просто:
var
uniq = function uniq(array) {
var
len = array.length;
while (len--) {
if (array.indexOf(array[len]) !== len) {
array.splice(len, 1);
}
}
return array;
},
myArray = [1, 2, 2, 4, 2];
console.log(uniq(myArray));
// [1, 2, 4];
Еще один ответ, просто потому, что я написал один для моего конкретного случая использования. В любом случае мне пришлось сортировать массив, и, учитывая, что я сортирую, я могу использовать это для дедупликации.
Обратите внимание, что моя сортировка имеет дело с моими конкретными типами данных, вам может потребоваться другая сортировка в зависимости от того, какие у вас элементы.
var sortAndDedup = function(array) {
array.sort(function(a,b){
if(isNaN(a) && isNaN(b)) { return a > b ? 1 : (a < b ? -1 : 0); }
if(isNaN(a)) { return 1; }
if(isNaN(b)) { return -1; }
return a-b;
});
var newArray = [];
var len = array.length;
for(var i=0; i<len; i++){
if(i === 0 || array[i] != array[i-1]){
newArray.push(array[i]);
}
}
};
Не цитируйте меня по этому поводу, но я думаю, что вам нужно использовать строку для имени вашего свойства, например o[e.toString()]
, а затем преобразовать его обратно, когда вы нажимаете его.
Array.prototype.unique=function(){
var cr=[];
this.forEach(function(entry) {
if(cr.indexOf(entry)<0){
cr.push(entry);
}else{
var index = cr.indexOf(entry);
if (index > -1) {
cr.splice(index, 1);
}
}
});
return cr;
}
Используйте.toString() для строк.
var givenvalues = [1,2,3,3,4,5,6];
var values = [];
for(var i=0; i<givenvalues.length; i++)
{
if(values.indexOf(givenvalues[i]) == -1)
{
values[values.length] = givenvalues[i];
}
}
Вы можете использовать вспомогательные функции массивов Reduce() и Some() для достижения вашего результата. Проверьте мой фрагмент кода:
var arrayWithDuplicates = [0, 0, 1, 2, 3, 3, 4, 4, 'a', 'a', '', '', null, null];
var arrayWithUniqueValues = arrayWithDuplicates
.reduce((previous, item) => {
if(!previous.some(element => element === item)) {
previous.push(item)
}
return previous;
}, []);
console.log('arrayWithUniqueValues', arrayWithUniqueValues)
Я посмотрел код Joeytje50 на jsperf, который сравнил ряд альтернатив. В его коде было много мелких опечаток, которые влияли на производительность и правильность.
Что еще более важно, он тестирует на очень маленьком массиве. Я сделал массив с 1000 целыми числами. Каждое целое число было в 100 раз случайным целым числом от 0 до 1000. Это составляет в среднем около 1000/e = 368 дубликатов. Результаты на jsperf.
Это гораздо более реалистичный сценарий того, где может потребоваться эффективность. Эти изменения вносят существенные изменения в претензии (в частности, код, рекламируемый как самый быстрый, далеко не скоро). Очевидные победители - те, где используются методы хеширования, причем лучший
Array.prototype.getUnique3 = function(){
var u = Object.create(null), a = [];
for(var i = 0, l = this.length; i < l; ++i){
if(this[i] in u) continue;
a.push(this[i]);
u[this[i]] = 1;
}
return a.length;
}