Ошибка при удалении дубликатов из массива Javascript
ОБНОВИТЬ
Вот небольшая проблема: https://jsfiddle.net/q9c5fku3/ когда я запускаю этот код и смотрю на консоль, я вижу, что это console.logging другого числа в массиве.
Спасибо за ваши ответы, извините, я получаю отрицательные отзывы, но это действительно смущает меня.
Я попробовал это снова, используя разные числа, интересно, вы, ребята, можете проверить эти цифры на своем конце и посмотреть, если вы получите другой результат?
var myArray = [621608617992776, 621608617992776, 10156938936550295, 621608617992776, 10156938936550295, 10156938936550295, 621608617992776, 10156938936550295];
console.log(myArray);
var myArrayTrimmed = [];
for(var i in myArray){
if(myArrayTrimmed.indexOf(myArray[i]) === -1){
myArrayTrimmed.push(myArray[i]);
}
}
console.log(myArrayTrimmed);
Это дает мне следующий массив в консоли:
[621608617992776, 10156938936550296]
Почему-то второе число увеличилось на 1.
====================
Оригинальный вопрос:
У меня есть этот массив:
var myArray = [100, 200, 100, 200, 100, 100, 200, 200, 200, 200];
Я пытаюсь создать новый массив с именем myArrayTrimmed
это будет то же самое как вышеупомянутый массив, за исключением того, что будут удалены дубликаты. Это должно привести к:
var myArrayTrimmed = [100, 200];
Вот код, который я использую, чтобы добиться этого:
var myArray = [100, 200, 100, 200, 100, 100, 200, 200, 200, 200];
var myArrayTrimmed = [];
for(var i in myArray){
if(myArrayTrimmed.indexOf(myArray[i]) === -1){
myArrayTrimmed.push(myArray[i]);
}
}
console.log(myArrayTrimmed);
Это не работает правильно, в то время как он удаляет дубликаты, по некоторым причинам он вычитает число 1
от 200, поэтому вывод в консоли:
[100, 199]
Я думаю, что это должно быть связано с -1
в коде, но я не знаю, как еще удалить дубликаты.
3 ответа
Я считаю, что это лучший способ сделать это
var myArray = [100, 200, 100, 200, 100, 100, 200, 200, 200, 200],
reduced = Object.keys(myArray.reduce((p,c) => (p[c] = true,p),{}));
console.log(reduced);
Хорошо... хотя это O(n), а остальные O(n^2), мне было любопытно увидеть сравнение эталонных тестов между этой таблицей уменьшения / поиска и комбинацией filter/indexOf (я выбрал очень хорошую реализацию Jeetendras /questions/10960523/oshibka-pri-udalenii-dublikatov-iz-massiva-javascript/10960533#10960533). Я готовлю массив из 100КБ, заполненный случайными положительными целыми числами в диапазоне 0-9999, и он удаляет дубликаты. Я повторяю тест 10 раз, и средние результаты показывают, что они не совпадают по производительности.
- В Firefox v47 уменьшить & lut: 14,85 мс против фильтра и indexOf: 2836 мс
- В Chrome v51 уменьшение & lut: 23,90 мс против фильтра и indexOf: 1066 мс
Ну хорошо, пока все хорошо. Но давайте сделаем это правильно в этот раз в стиле ES6. Это выглядит так круто..! Но на данный момент, как он будет работать против мощного решения Lut, для меня загадка. Давайте сначала посмотрим код, а затем сравните его.
var myArray = [100, 200, 100, 200, 100, 100, 200, 200, 200, 200],
reduced = [...myArray.reduce((p,c) => p.set(c,true),new Map()).keys()];
console.log(reduced);
Вау, это было коротко..! Но как насчет производительности..? Это прекрасно... Так как большой вес фильтра / indexOf перевалил за наши плечи, теперь я могу протестировать массив 1M случайных элементов натуральных чисел в диапазоне 0..99999, чтобы получить среднее значение из 10 последовательных тестов. Я могу сказать, что на этот раз это настоящий матч. Смотрите результат для себя:)
var ranar = [],
red1 = a => Object.keys(a.reduce((p,c) => (p[c] = true,p),{})),
red2 = a => reduced = [...a.reduce((p,c) => p.set(c,true),new Map()).keys()],
avg1 = [],
avg2 = [],
ts = 0,
te = 0,
res1 = [],
res2 = [],
count= 10;
for (var i = 0; i<count; i++){
ranar = (new Array(1000000).fill(true)).map(e => Math.floor(Math.random()*100000));
ts = performance.now();
res1 = red1(ranar);
te = performance.now();
avg1.push(te-ts);
ts = performance.now();
res2 = red2(ranar);
te = performance.now();
avg2.push(te-ts);
}
avg1 = avg1.reduce((p,c) => p+c)/count;
avg2 = avg2.reduce((p,c) => p+c)/count;
console.log("reduce & lut took: " + avg1 + "msec");
console.log("map & spread took: " + avg2 + "msec");
Какой бы вы использовали..? Ну, не так быстро...! Не обманывайтесь. Карта находится в смещении. Теперь посмотрите... во всех вышеупомянутых случаях мы заполняем массив размером n числами диапазона Теперь это захватывающее возвращение Map()..! Может быть, теперь вы можете принять лучшее решение, когда вы хотите удалить обманщиков. Ну ладно, теперь мы все счастливы. Но главная роль всегда идет с аплодисментами. Я уверен, что некоторые из вас задаются вопросом, что будет делать объект Set. Теперь, когда мы открыты для ES6 и знаем, что Map - победитель предыдущих игр, давайте сравним Map с Set как финал. На этот раз типичная игра "Реал Мадрид - Барселона"... или это так? Посмотрим, кто победит в эль классико:) Вау.. человек..! Что ж, неожиданно это вовсе не оказалось el classico. Больше похоже на ФК Барселона против CA Osasuna:))var ranar = [],
red1 = a => Object.keys(a.reduce((p,c) => (p[c] = true,p),{})),
red2 = a => reduced = [...a.reduce((p,c) => p.set(c,true),new Map()).keys()],
avg1 = [],
avg2 = [],
ts = 0,
te = 0,
res1 = [],
res2 = [],
count= 100;
for (var i = 0; i<count; i++){
ranar = (new Array(100000).fill(true)).map(e => Math.floor(Math.random()*100000000));
ts = performance.now();
res1 = red1(ranar);
te = performance.now();
avg1.push(te-ts);
ts = performance.now();
res2 = red2(ranar);
te = performance.now();
avg2.push(te-ts);
}
avg1 = avg1.reduce((p,c) => p+c)/count;
avg2 = avg2.reduce((p,c) => p+c)/count;
console.log("reduce & lut took: " + avg1 + "msec");
console.log("map & spread took: " + avg2 + "msec");
var ranar = [],
red1 = a => reduced = [...a.reduce((p,c) => p.set(c,true),new Map()).keys()],
red2 = a => Array.from(new Set(a)),
avg1 = [],
avg2 = [],
ts = 0,
te = 0,
res1 = [],
res2 = [],
count= 100;
for (var i = 0; i<count; i++){
ranar = (new Array(100000).fill(true)).map(e => Math.floor(Math.random()*10000000));
ts = performance.now();
res1 = red1(ranar);
te = performance.now();
avg1.push(te-ts);
ts = performance.now();
res2 = red2(ranar);
te = performance.now();
avg2.push(te-ts);
}
avg1 = avg1.reduce((p,c) => p+c)/count;
avg2 = avg2.reduce((p,c) => p+c)/count;
console.log("map & spread took: " + avg1 + "msec");
console.log("set & A.from took: " + avg2 + "msec");
Вы можете использовать приведенный ниже код для эффективного удаления дублирующихся элементов -
var myArrayTrimmed = myArray.filter(function(elem, pos) {
return myArray.indexOf(elem) == pos;
});
myArrayTrimmed будет содержать уникальные значения.
Надеюсь, это будет полезно
var myArray = [100, 200, 100, 200, 100, 100, 200, 200, 200, 200];
var myArrayTrimmed = [];
myArray.forEach(function(item){
if(myArrayTrimmed.indexOf(item) ==-1){
myArrayTrimmed.push(item);
}
})
console.log(myArrayTrimmed);
Проверьте это jsfiddle