Comments 20
UFO just landed and posted this here
для больших массивов функция unique будет работать небыстро.
я обычно делаю так:
PS. 'z'+val а не просто val для корректной работы при случае, когда к Object-у добавлены новые методы через prototype.
я обычно делаю так:
Array.prototype.unique = function() {
var res = [];
var already = {};
for (var i = 0; i < this.length; i++) {
var val = this[i];
if (typeof(already['z'+val]) == 'undefined') {
res.push(val);
already['z'+val] = true;
}
}
return res;
}
PS. 'z'+val а не просто val для корректной работы при случае, когда к Object-у добавлены новые методы через prototype.
0
Согласен, этот вариант тоже хорош, мне он даже несколько больше нравится :)
0
Догадайтесь что вернет ваша функция в таком случае
еще пример
[{val:1},{val:2},{val:3}].unique();
еще пример
[1,'1',[1,2,3],'1,2,3'].unique();
0
оно не работает для таких случаев.
но мне кажется что эти случаи искуственно придуманы, и в реальности будут встречатся несравненно редко (по крайней мере если мне надо было делать юник, то все объекты были однородными (да, и у всех был метод наподобие get_id или get_value, чтобы получать одно ключевое поле))
но мне кажется что эти случаи искуственно придуманы, и в реальности будут встречатся несравненно редко (по крайней мере если мне надо было делать юник, то все объекты были однородными (да, и у всех был метод наподобие get_id или get_value, чтобы получать одно ключевое поле))
0
Array.prototype.unique = function () {
var obj = new Object();
var elem;
for (let i = 0; elem = this[i]; ++i) {obj[elem] = 1};
var arr = [];
for (elem in obj) {arr.push(elem)};
return arr;
}
0
ваш метод почти аналогичен моему, и обладает теми же недостатками что и мой :)
а кроме того если в Object добавлены новые методы через prototype (так любит делать одноимённая библиотека), то будет не верный результат.
например:
Object.prototype.new_method_1 = function() { /* do something */ }
Object.prototype.new_method_2 = function() { /* do something */ }
arr = [1, 2, 3, 1, 1, 2];
alert(arr.unique());
а кроме того если в Object добавлены новые методы через prototype (так любит делать одноимённая библиотека), то будет не верный результат.
например:
Object.prototype.new_method_1 = function() { /* do something */ }
Object.prototype.new_method_2 = function() { /* do something */ }
arr = [1, 2, 3, 1, 1, 2];
alert(arr.unique());
0
for(j=0;j<=this.length-1;j++)
Все нормальный программисты пишут так :)
for(var j = 0; j < this.length; j++)
В вашем случае j станет глобальной, что уже не хорошо. И одна лишняя операция вычитания. К тому же строка '123' и число 123 у вас будут считаться одним и тем же, что не совсем верно - лучше использовать оператор === (эквивалентно) вместо == (равно). Ваш contains работает похоже с методом indexOf, который вошел в JS в 1.5 (или 1.6, все время путаю) и поддерживается многими современными браузерами. Только в случае с indexOf он возвращает индекс где находится найденный элемент, или -1 если элемент не найден, что дает больше возможностей и более широкое применение.
По поводу unique. Реализация самая простая, асимптотика одна и плохих N^2/2 (N квадрат пополам). Плюс издержки на вызов метода/функции (contains). Перепишите с вложенным массивом будет прирост производительности. Перепишите алгоритм, например можно отсортировать массив, а потом "схлопнуть" дубликаты - получим N*log(N), что значительно лучше (единственное что могут быть проблемы с объектами, но это тоже можно решить).
+1
Спасибо большое за дельное предложение. Плюсов вам в карму :)
Эта реализация написана достаточно быстро, фактически, на скорую руку, так что особой производительности я от нее не ожидал. Я обязательно воспользуюсь вашим советом, перепишу функцию и снова выложу на оценку :)
Эта реализация написана достаточно быстро, фактически, на скорую руку, так что особой производительности я от нее не ожидал. Я обязательно воспользуюсь вашим советом, перепишу функцию и снова выложу на оценку :)
0
ну и добавить, что вычитание быстрее,
поэтому есть смысл в for(var j=this.length-1;j>=0;j--)
Еще примеры реализации указанных ф-ий (взято с brainjacked.com):
Array.prototype.indexOf = function(element) {
var i = this.length;
for(i;i>-1 && element != this[i];i--);
return i;
}
Array.prototype.distinct = function() {
for(var i=0;i<this.length;i++)
for(var j=(i+1);j<this.length;j++)
if(this[i]==this[j])
this.splice(j--,1);
return this;
}
поэтому есть смысл в for(var j=this.length-1;j>=0;j--)
Еще примеры реализации указанных ф-ий (взято с brainjacked.com):
Array.prototype.indexOf = function(element) {
var i = this.length;
for(i;i>-1 && element != this[i];i--);
return i;
}
Array.prototype.distinct = function() {
for(var i=0;i<this.length;i++)
for(var j=(i+1);j<this.length;j++)
if(this[i]==this[j])
this.splice(j--,1);
return this;
}
0
Да, можно по всякому написать - я написал самую распространенную == привычную форму.
По тексту indexOf
1. Это не работает. Тесты:
2. Если уж писать кратко (и не обращать на то что функция в корне работает неверно) то, можно записать так:
Ну и distinct просто ужасна! Использование splice очень негативно скажется на скорости, здесь ее использование очень дорого. И в итоге получаем тот же N^2/2 и сдается мне что даже хуже.
По тексту indexOf
1. Это не работает. Тесты:
[].indexOf(); // вернет 0, должен -1
[].indexOf(null); // вернет 0, должен -1
[1,2].indexOf(); // вернет 2, должен -1
[1,2].indexOf(null); // вернет 2, должен -1
[undefined].indexOf(); // вернет 1, должен 0
[1,2,3,2].indexOf(2); // вернет 3, должен 1; в стандарте прописано что
возвращаемый индекс должен быть с начала массива (если не указан необязательный аргумент offset, который тут попросту опустили)
[1,0,2].indexOf(false); // вернет 1, должен -1; я искал false, а не ноль
[1,0,2].indexOf(''); // вернет 1, должен -1; я искал пустую строку, а не ноль
[1,'',2].indexOf(0); // вернет 1, должен -1; я искал ноль, а не пустую строку
и т.д.
2. Если уж писать кратко (и не обращать на то что функция в корне работает неверно) то, можно записать так:
Array.prototype.indexOf = function(element) {
for(var i = this.length; --i > -1 && element !== this[i];);
return i;
}
// я все таки добавил пару маленьких фиксов
Ну и distinct просто ужасна! Использование splice очень негативно скажется на скорости, здесь ее использование очень дорого. И в итоге получаем тот же N^2/2 и сдается мне что даже хуже.
0
А в prototype есть готовое решение - Array.unuq(), хотя и не очень шустрое
0
Нужно было не в мануале jQuery искать, а в коде. $.unique(array)
А добвалять новые методы ни массиву, ни объекту не советуют.
А добвалять новые методы ни массиву, ни объекту не советуют.
0
В мануале тоже есть. Плохо искали: http://docs.jquery.com/Utilities/jQuery.…
0
Sign up to leave a comment.
Парочка полезных функций