Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
C++. Мастер-класс в задачах и примерах. Авторы: Кузнецов М.В., Симдянов И.В. PHP на примерах (2 издание). Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель MySQL 5. Авторы: Кузнецов М.В., Симдянов И.В. Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В. MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

HTML+CSS+JavaScript

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Поиск уникальных значений: как ускорить?
 
 автор: HelloMoto   (04.12.2009 в 22:45)   письмо автору
 
 

Форумчане, доброго времени суток :)

Есть проблемка, помогите решить её.
Имееем код:


    var project;
    var projects = [];
    var uniqueProjects = [];

function f1() {
    for(var i = 1; i < length1; i++) {
    ...
        for(var j = 0; j < length2; j++) {
        ...
            projects.push(project);
        }
    }

    uniqueProjects = arrayUnique(projects);

    for(k = 0; k < uniqueProjects.length; k++) {

    ...uniqueProjects[k]...

//здесь, скажем так, 'главный код' :) В  циклах выше, я создавал массив projects со всеми элементами project, потом выбирал уникальные значения - uniqueProjects = arrayUnique(projects);. После моих изменений всё работает в 3-4 раза медленнее..  Это не есть гут!

    }
}


function arrayUnique(ar) {
    var a = [];
    var l = ar.length;
    for(var i = 0; i < l; i++) {
        for(var j = i + 1; j < l; j++) {
            if(ar[i] === ar[j])
                j = ++i;
        }
        a.push(ar[i]);
    }
    return a;
}


Как ускорить поиск уникальных значений в данном случае? По-моему метод push() и arrayUnique() работает медленно... Какие мысли у кого?

  Ответить  
 
 автор: АЯ   (05.12.2009 в 07:30)   письмо автору
 
   для: HelloMoto   (04.12.2009 в 22:45)
 

Много быстрее:
function arrayUnique (ar)
{
for (var s = [], r = [], j = k = 0, x = ar.length; j < x; j++)
if (!s [ar [j]]) {s [ar [j]] = 69; r [k++] = ar [j]} return r;
}
и безо всяких "пушей".

  Ответить  
 
 автор: HelloMoto   (05.12.2009 в 14:00)   письмо автору
 
   для: АЯ   (05.12.2009 в 07:30)
 

s [ar [j]] = 69;
- что это значит?

  Ответить  
 
 автор: АЯ   (05.12.2009 в 23:02)   письмо автору
 
   для: HelloMoto   (05.12.2009 в 14:00)
 

Это значит то же самое, что и:
s [ar [j]] = 3.1415926; 
или
s [ar [j]] = true;
или
s [ar [j]] = 'Abrakadabra';
и вообще всё что угодно, КРОМЕ:
нуля, undefined, null, пустой строки или false.

  Ответить  
 
 автор: HelloMoto   (07.12.2009 в 17:29)   письмо автору
 
   для: АЯ   (05.12.2009 в 23:02)
 

А подскажите плз ещё вот что - как в вашей функции возвращать true если в r добавлен новый уникальный элемент и false в любом другом?

  Ответить  
 
 автор: АЯ   (07.12.2009 в 18:03)   письмо автору
 
   для: HelloMoto   (07.12.2009 в 17:29)
 

Извините, последний ваш вопрос я не понял.
Как мне видится, вы передаёте функции один массив,
в котором могут быть повторяющиеся элементы:
massiv_1 = ['Иванов', 'Петров', 'Иванов', 'Сидоров', 'Кузнецов', 'Иванов'];

Задача функции - вычеркнуть "второго" и "третьего" Иванова,
оставив первого:
['Иванов', 'Петров', 'Иванов', 'Сидоров', 'Кузнецов', 'Иванов'];
т.е. вернуть на выходе другой массив, в котором нет "однофамильцев"
и есть только один Иванов (уникальный):
massiv_2 = ['Иванов', 'Петров', 'Сидоров', 'Кузнецов'];

Моя функция с этим справляется. "Быстро и дешево".

Что вам надо?
Вы хотите добавить какую-то ещё "функциональность" для этой функции?
Или же просто хотите понять механизм работы этой функции?
Объясните подробнее.

  Ответить  
 
 автор: HelloMoto   (07.12.2009 в 18:22)   письмо автору
 
   для: АЯ   (07.12.2009 в 18:03)
 

Походу задача немного меняется.
Надо вот что:
- есть массив ar, содержащий абсолютно любые элементы.
В функции arrayUnique(), проходя по массиву ar, в случае если текущего значения нет в массиве ar, то есть оно уникальное, вернуть true, иначе вернуть false. То есть arrayUnique должна возвращать true или false.

То есть:
....
if(arrayUnique(ar, a)){ // вызов 
....
function arrayUnique(ar, a) {
    ar.push(a);

вот здесь нужно делать то, что я написал выше

}

  Ответить  
 
 автор: АЯ   (07.12.2009 в 18:37)   письмо автору
 
   для: HelloMoto   (07.12.2009 в 18:22)
 

Как-то вы невнятно объясняетесь. Или у меня с "понималкой" плохо сегодня :-)

Сейчас я понял только то, что вам нужна иная функция.
И понял, что в функцию вы теперь передаёте два аргумента: массив и отдельный
элемент.
Возвращаясь к моей "аналогии с однофамильцами", вы передаёте какой-то
"список фамилий" и ещё одну фамилию отдельно.

Но я не понял - что функция должна делать и что возвращать?
Судя по первой строке функции из вашего примера входящий "список фамилий"
по-любому пополняется ещё одной переданной отдельной фамилией - ar.push(a);.
А что функция тогда должна ЕЩЁ делать и что возвращать?

  Ответить  
 
 автор: HelloMoto   (07.12.2009 в 18:46)   письмо автору
 
   для: АЯ   (07.12.2009 в 18:37)
 

при вызове if(arrayUnique(ar, a)), передаётся два параметра ar - пустой массив и a - элемент(string), которыми заполняется массив в функции arrayUnique(): ar.push(a)
Этот вызов - if(arrayUnique(ar, a)) - происходит в цикле for, то есть массив ar заполняется элементами a.
Во время заполнения массива ar мы должны брать текущее значение a и проверять есть ли такое же в массиве ar. Если есть, то возвращать false, если его нет, то возвращать true.

Сейчас понятно или нет? :)

  Ответить  
 
 автор: АЯ   (07.12.2009 в 19:09)   письмо автору
 
   для: HelloMoto   (07.12.2009 в 18:46)
 

Так, вроде бы понял.
Вам по-любому надо Иванова к списку добавить, но при этом сообщить - первый
ли это Иванов в списке или же у него же были однофамильцы в этом списке.

Ну это вы и сами можете сделать:

1. или циклом перебирайте весь массив и сравнивайте с новым элементом; как
только встретите Иванова, так и выходите из цикла брейком (чтобы третьих и
четвертых "ивановых" не искать)

2. или преобразуйте массив в строку (с каким-то уникальным
разделителем) + добавьте этот же разделитель в начало и конец и методом
search () ищите совпадение в этой строке
с RegExp = 'разделитель' + новый_элемент + 'разделитель';.
Но это много медленнее первого варианта.

---
Кстати, зря вы "упёрлись" в метод push () - он тормозной. Запустите:
<script>
var s = [1, 2, 3], d = 4;

function arrayUnique (ar, a) {ar.push (a)}
function faster (ar, a) {ar [ar.length] = a}

var T1 = new Date ().valueOf (); for (var j = 0; j < 98765; j++) arrayUnique (s, d);
var T2 = new Date ().valueOf (); for (var j = 0; j < 98765; j++) faster (s, d);
var T3 = new Date ().valueOf ();

alert ('push () работает ~ в ' + (T2 - T1) / (T3 - T2) + ' раза медленнее');
</script>
и удостоверьтесь.

  Ответить  
 
 автор: HelloMoto   (07.12.2009 в 22:01)   письмо автору
 
   для: АЯ   (07.12.2009 в 19:09)
 

...
for(...){
    if(arrayUnique(projects, project)){...}
}
...
function arrayUnique(projects, project) {
    var isExist;
    projects [projects.length] = project;
    for(var i=0; i <= projects.length; i++){
        if(projects[i] == project){
            isExist = false;
            break;
        } else {isExist = true;break;}
    }
return isExist;
}


С каждым вызовом arrayUnique в цикле for массив projects заполняется разными значениями - как одинаковыми, так и нет. Что-то не то.. работает некорректно :(
Что не так? туплю...
Мне надо возвращать true только тогда, когда текущего значения в массиве нет. Как изменить моё условие, оно неверное, я вижу )

  Ответить  
 
 автор: AlexSol   (07.12.2009 в 23:10)   письмо автору
 
   для: HelloMoto   (07.12.2009 в 22:01)
 

текущее значение всегда будет в массиве. вы проверяйте сначала, а потом добавляйте его.
перенесите в конец функции projects [projects.length] = project;

  Ответить  
 
 автор: АЯ   (07.12.2009 в 23:20)   письмо автору
 
   для: HelloMoto   (07.12.2009 в 22:01)
 

function arrayUnique (projects, project)
{
for (var r = true, j = 0, l = projects.length; j < l; j++)
if (projects [j] == project) {r = false; break}
projects [l] = project; return r;
}

//для проверки
var pros = ['Иванов', 'Петров', 'Сидоров', 'Кузнецов'];
var pro_1 = 'Иванов'; //имеется
var pro_2 = 'Шариков'; //уникальное

alert (arrayUnique (pros, pro_1)); //false для Иванова
alert (arrayUnique (pros, pro_2)); //true для Шарикова

  Ответить  
 
 автор: HelloMoto   (08.12.2009 в 13:36)   письмо автору
 
   для: АЯ   (07.12.2009 в 23:20)
 

Да, всё ОК!

Спасибо, AlexSol.

Отдельное спасибо вам, АЯ! Спасибо, что вы есть! :)

  Ответить  
 
 автор: HelloMoto   (08.12.2009 в 14:29)   письмо автору
 
   для: HelloMoto   (08.12.2009 в 13:36)
 

Эх.. всё же ещё вопросик..
а как здесь

for (var r = true, j = 0, l = projects.length; j < l; j++)
if (projects [j] == project) {r = false; break}
projects [l] = project; return r; 

можно заюзать hashmap вместо массива? Ну чтобы не по массиву бегать, а по hashmap...

  Ответить  
 
 автор: АЯ   (08.12.2009 в 15:54)   письмо автору
 
   для: HelloMoto   (08.12.2009 в 14:29)
 

Если изначально (в первый раз) передаваемый массив будет у вас пустым, то можно.

Но hashmap нужен будет глобальный - до первого обращения к функции вам надо его объявить.
<script>
var H = new Array ();

//...

function arrayUnique (projects, project)
{
var r = (!H [project]) ? true : false; H [project] = 9;
projects [projects.length] = project; return r;
}

//вызов функции arrayUnique ()

  Ответить  
 
 автор: HelloMoto   (09.12.2009 в 14:53)   письмо автору
 
   для: АЯ   (08.12.2009 в 15:54)
 

АЯ, ммм... не совсем то..
Надо заюзать вот это: var hash = {};, где по ключу будем искать.... так как текущий вариант медленно работает из-за поиска в массиве....

  Ответить  
 
 автор: АЯ   (09.12.2009 в 16:36)   письмо автору
 
   для: HelloMoto   (09.12.2009 в 14:53)
 

Вы разберитесь с "текущим вариантом" (с последним кодом) - там как раз ищется по ключу.
И ваш var hash = {}; - он уже "заюзан" как var H = new Array ();
И работает всё как раз быстро как только можно - никакого "поиска по массиву" нет.

  Ответить  
 
 автор: HelloMoto   (09.12.2009 в 19:26)   письмо автору
 
   для: АЯ   (09.12.2009 в 16:36)
 

Да, точно!
АЯ, Большое-прибольшое Вам Спасибо!!! :)

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования