Модераторы: korob2001, ginnie

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Массив и условие 
:(
    Опции темы
Ramirez
Дата 9.9.2006, 00:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 305
Регистрация: 18.1.2005
Где: Moscow, ExUSSR

Репутация: 4
Всего: 5



Замечательно. По-моему, посты товарища Nab'a вполне достойны размещения в каком нить FAQ.
Вот кстати, иногода бывает такая ситуация:
Код

@arr = qw(4 10 16 20);
$hash{$_} = $_ foreach @arr;


т.е. из списка надо сделать хеш где значение ключа равно его(ключа) имени.
мне кажется должен быть более красивый вариант, без foreach...
PM ICQ   Вверх
Nab
Дата 9.9.2006, 01:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 582
Регистрация: 25.3.2006
Где: Kiev

Репутация: 26
Всего: 37



Цитата(Ramirez @  9.9.2006,  00:15 Найти цитируемый пост)
Замечательно. По-моему, посты товарища Nab'a вполне достойны размещения в каком нить FAQ.

Спасибо конечно smile

А по существу, то,  наверно вот так :
Код

@arr = qw(4 10 16 20);    
@{%hash}{@arr} = @arr;



--------------------
 Чтобы правильно задать вопрос нужно знать больше половины ответа...
Perl Community 
FREESCO in Ukraine 
PM MAIL   Вверх
korob2001
Дата 10.9.2006, 04:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2871
Регистрация: 29.12.2002

Репутация: 31
Всего: 61



Ещё, как вариант:
Код

my $number = 16;
my @array = qw(4 10 16 20);

print "Exists" if "@array" =~ /\b$number\b/;



--------------------
"Время проходит", - привыкли говорить вы по неверному пониманию. 
"Время стоит - проходите вы".
PM MAIL WWW ICQ MSN   Вверх
sharq
Дата 11.9.2006, 09:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Perl Liker
**


Профиль
Группа: Участник
Сообщений: 841
Регистрация: 13.12.2004
Где: Ростов-на-Дону

Репутация: 23
Всего: 28



korob2001, отличный вариант! Супер!  smile 




--------------------
[color=gray]There's More Than One Way To Do It[/color]
PM MAIL WWW ICQ Skype   Вверх
amg
Дата 12.9.2006, 08:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1145
Регистрация: 3.8.2006
Где: Новосибирск

Репутация: 38
Всего: 50



Нравится мне этот форум! Есть над чем подумать.
Вот, например, здесь предложили несколько вариантов решения практически важной задачи: выяснить, присутствует ли в списке данный элемент. Мне часто приходится иметь дело с огромными списками, поэтому я эти варианты поисследовал на предмет эффективности. Привожу результаты, может, кому-нибудь еще будет интересно.
Код

$cifra = 30; @massiv = ('4', '10', '16', '20') x 1e6;

# Nab
@{%mass}{@massiv} = (1) x @massiv; print "OK\n" if exists $mass{$cifra};

# diverd
foreach (@massiv) {print "OK\n" if $_==$cifra}

# sharq
print "OK\n" if (grep {$cifra == $_} @massiv);

# Nab1
print "OK\n" if map {/^\Q$cifra\E$/} @massiv;

# korob2001
print "OK\n" if "@massiv" =~ /\b$cifra\b/;

# List::Util
use List::Util qw(first); print "OK\n" if first { $cifra == $_ } @massiv;

Результаты:
Код

          Время,с Память,Mb
Nab         1.39  124
diverd      1.88   61
sharq       0.79   61
Nab1        3.50    0
korob2001   0.69   21
List::Util  0.65   61

Я для себя запомню два варианта: "korob2001" - совершенно неожиданный, но очень эффективный, и "Nab1" - не быстрый, но зато не требующий дополнительной памяти.

PM MAIL   Вверх
Nab
Дата 12.9.2006, 08:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 582
Регистрация: 25.3.2006
Где: Kiev

Репутация: 26
Всего: 37



amg, ты манияк от перла smile  Оптимизатор блин smile

Кстати мне не понятны результаты вариантов diverd и sharq, они по идее аналогичны моему, но отжирают памяти порядочно smile. 

Конечно они быстрее, но ...  Видно какое-то оптимизирующее кеширование применяется... И похоже что одинаковое.


Это сообщение отредактировал(а) Nab - 13.9.2006, 03:57


--------------------
 Чтобы правильно задать вопрос нужно знать больше половины ответа...
Perl Community 
FREESCO in Ukraine 
PM MAIL   Вверх
Nab
Дата 12.9.2006, 09:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 582
Регистрация: 25.3.2006
Где: Kiev

Репутация: 26
Всего: 37



Кстати в моем первом варианте, вопрос не до конца продуман

Код

$cifra = 30; @massiv = ('4', '10', '16', '20') x 1e6;    

@{%mass}{@massiv} = (1) x @massiv; print "OK\n" if exists $mass{$cifra};


Ведь в реальности получается что все время потрачено на заполнение и конвертирование одной формы списка в другую, хеш. Хотя у большинства это было просто заполнение массива. Я бы наверно предпочел сразу формировать хеш а не первоначальный список, но идея даже не в этом... smile
Так как в список уникальных значений всего 4 то хеш в конечном итоге получиться всего из 4 элементов, и поиск по нему будет мизерно быстр smile тут нужно или заполнять список уникальными значениями, типа i++ или сразу из них же формировать хеш, думаю результат будет другим smile. попробуешь? для чистоты эксперимента?

Вариант 1
Код

$cifra = 1e6 + 1; while ($i < 1e6) {$massiv[$i++] = 1};    

@{%mass}{@massiv} = (1) x @massiv; print "OK\n" if exists $mass{$cifra};


Вариант 2
Код

$cifra = 1e6 + 1; while ($i < 1e6) {$massiv[$i++] = 1};    

print "OK\n" if exists $mass{$cifra};


можно пргнать с уникальным списком все варианты smile


--------------------
 Чтобы правильно задать вопрос нужно знать больше половины ответа...
Perl Community 
FREESCO in Ukraine 
PM MAIL   Вверх
amg
Дата 12.9.2006, 12:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1145
Регистрация: 3.8.2006
Где: Новосибирск

Репутация: 38
Всего: 50



Ага, когда компутер сначала надолго замолкает, а потом начинает молотить диском, впадая в глухой своп, поневоле станешь оптимизатором.

Мне вот тоже непонятно, почему вариант "Nab1" не требует памяти, хотя, на первый взгляд, должен, а "diverd" - требует, хотя, казалось бы, и незачем. В общем, много еще нужно учиться.

ЗЫ Это я на предыдущий пост...

Это сообщение отредактировал(а) amg - 12.9.2006, 12:23
PM MAIL   Вверх
amg
Дата 12.9.2006, 13:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1145
Регистрация: 3.8.2006
Где: Новосибирск

Репутация: 38
Всего: 50



Цитата(Nab @  12.9.2006,  09:37 Найти цитируемый пост)
... Ведь в реальности получается что все время потрачено на заполнение ...
 Нет, время на заполнение первоначального массива не учитывалось.
Цитата
Так как в список уникальных значений всего 4 то хеш в конечном итоге получиться всего из 4 элементов, и поиск по нему будет мизерно быстр
 Дополнительное время (см. ниже) тратится, видимо, на формирование хэша с более, чем 4 элементами. А поиск по хэшу я уже проверял, он пренебрежимо быстр и для очень больших хэшей (удивительно, однако). 
Цитата
тут нужно или заполнять список уникальными значениями, типа i++ . попробуешь? для чистоты эксперимента?
С удовольствием! 
Код

$cifra = 4e6 + 1; while ($i < 4e6) {$massiv[$i++] = 1};
Код

          Время,с
Nab         2.68
diverd      1.09
sharq       0.78
Nab1        3.31
korob2001   0.65
List::Util  0.63
 Фактически, изменились первые две строчки, в 1-й замедление (можно понять, почему), во 2-й - ускорение (непонятно почему)

PM MAIL   Вверх
sharq
Дата 12.9.2006, 13:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Perl Liker
**


Профиль
Группа: Участник
Сообщений: 841
Регистрация: 13.12.2004
Где: Ростов-на-Дону

Репутация: 23
Всего: 28



amg, интересно с помощью чего ты время тестировал? 
Попробуй Benchmark и повторов этак 10_000, привиди код и результаты.
А с помощью Memchmark замереть память - не совсем хорошо, т.к.
Цитата

BUGS ^

This is a very early release, alpha software, expect bugs on it.

The API is not stable. I will change it when required for improvement.


А на счет вариантов мое мнение - вариант korob2001 - красивый, быстро работает из-за регулярных выражений, но есть недостатки, н-р - не найдешь индекс, найденного эелемента.
Мой вариант - это стандартный  в данной ситуации, в стиле Perl, но также есть недостатки.
Вариант Nab (последний) - это вариант языка Си, прелести Perl нет. А первый вариант - map для этого не используется.
List::Util - хороший модуль, но он загружается в память и для небольшой задачи это не нужно!
Обычным перебором - хорошо, но не красиво  smile 

Итог - вариант стоит использовать тот, кот. в данный ситуации будет наиболее приемлем.
Н-р, я использую всегда красивый вариант, если не требуется оптимального решения! Поэтому grep и regexp - это то, что надо.

 smile 



--------------------
[color=gray]There's More Than One Way To Do It[/color]
PM MAIL WWW ICQ Skype   Вверх
Nab
Дата 12.9.2006, 17:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 582
Регистрация: 25.3.2006
Где: Kiev

Репутация: 26
Всего: 37



Все верно ребята вы говорите smile 

Но как я сказал в предыдущем посте, то к примеру я, если мне нужно проверять наличие значения как такового, изначально использовал бы хеш. Ведь все равно производиться заполнение, массива или хеша, а в последствии к хешу доступ по этому параметру намного быстрее. Другое дело объем памяти smile Но тут все зависит от назначения этих операций, и считать нужно будет уже комплексно по работе всей системы, а не по одному выражению.

Ну и конечно о красоте smile Прелесть перла, что это можно сделать не одним способом smile  А красота у всех разная ... 
Хотя мои решения с map не такое уж страшное, и как оказалось и в нем есть рациональное зерно smile

PS: amg, а покаж ка, как ты мерял?


--------------------
 Чтобы правильно задать вопрос нужно знать больше половины ответа...
Perl Community 
FREESCO in Ukraine 
PM MAIL   Вверх
Danissimo
Дата 12.9.2006, 17:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 150
Регистрация: 14.8.2006
Где: Санкт-Петербург

Репутация: 1
Всего: 1



amg, хочу сказать, не удивляйся, что время поиска по хеш-таблице не зависит от количества элементов. Если посмотреть на цели, с которыми разрабатывались хеш-таблицы, то именно эта цель и преследовалась, а именно: время поиска не должно зависеть от количества элементов, то есть должно быть константным. На языке алгоритмического анализа это записывается так: O(n) = const =)) Я не знаю никакой другой структуры данных, у которой алгоритмическая сложность была бы величиной постоянной. Так что все работает, как и должно =)
PM MAIL   Вверх
korob2001
Дата 13.9.2006, 03:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2871
Регистрация: 29.12.2002

Репутация: 31
Всего: 61



Кстати, amg если будет желаение, можешь попробовать компилировать шаблон только один раз, т.е. добавить модификатор "о" к регулярному выражению. Ведь у нас всё равно не меняется значение переменной $number.
Код

print "Exists" if "@array" =~ /\b$number\b/o;



--------------------
"Время проходит", - привыкли говорить вы по неверному пониманию. 
"Время стоит - проходите вы".
PM MAIL WWW ICQ MSN   Вверх
amg
Дата 13.9.2006, 12:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1145
Регистрация: 3.8.2006
Где: Новосибирск

Репутация: 38
Всего: 50



Цитата(sharq @  12.9.2006,  13:58 Найти цитируемый пост)
amg, интересно с помощью чего ты время тестировал? Попробуй Benchmark и повторов этак 10_000, привиди код и результаты.
Использовал два способа. 1. Тупое замерение времени до и после куска кода:
Код

use Time::HiRes qw( time );

$cifra = 30; @massiv = ('4', '10', '16', '20') x 1e6;

$time0 = time();
@{%mass}{@massiv} = (1) x @massiv; print "OK\n" if exists $mass{$cifra};
$time1 = time(); print "Nab: \t", $time1 - $time0, "\n";

$time0 = time();
foreach (@massiv) {print "OK\n" if $_==$cifra}
$time1 = time(); print "diverd: \t", $time1 - $time0, "\n";

$time0 = time();
print "OK\n" if (grep {$cifra == $_} @massiv);
$time1 = time(); print "sharq: \t", $time1 - $time0, "\n";

$time0 = time();
print "OK\n" if map {/^\Q$cifra\E$/} @massiv;
$time1 = time(); print "Nab1: \t", $time1 - $time0, "\n";

$time0 = time();
print "OK\n" if "@massiv" =~ /\b$cifra\b/;
$time1 = time(); print "korob2001: \t", $time1 - $time0, "\n";

$time0 = time();
use List::Util qw(first); print "OK\n" if first {$cifra == $_} @massiv;
$time1 = time(); print "List::Util: \t", $time1 - $time0, "\n";
 2. Benchmark
Код

use Benchmark qw(:all);

$cifra = 30; @massiv = ('4', '10', '16', '20') x 1e6;

timethese(-10,{
Nab => sub {
@{%mass}{@massiv} = (1) x @massiv; print "OK\n" if exists $mass{$cifra};
},

diverd => sub {
foreach (@massiv) {print "OK\n" if $_==$cifra}
},

sharq => sub {
print "OK\n" if (grep {$cifra == $_} @massiv);
},

Nab1 => sub {
print "OK\n" if map {/^\Q$cifra\E$/} @massiv;
},

korob2001 => sub {
print "OK\n" if "@massiv" =~ /\b$cifra\b/;
},

'List::Util' => sub {
use List::Util qw(first); print "OK\n" if first { $cifra == $_ } @massiv;
},
});
 
Результаты (больше проценты - быстрее).
Код

          Прямое измерение времени       Benchmark            Benchmark
            массив 4e6 элементов    массив 4e6 элементов  массив 4 элемента
Nab                 256%                    218%                 88%
diverd              192%                    245%                 86%
sharq               436%                    390%                219%
Nab1                100%                    100%                100%
korob2001           503%                    543%                127%
List::Util          542%                    506%                144%
 На большом массиве результаты обоих способов похожи (естественно). Любопытно, что на маленьком массиве все совсем по-другому. Быстрее всех становится вариант "sharq". Этот вариант хорош еще и тем, что он самый "читабельный" (для меня).

Цитата
А с помощью Memchmark замереть память - не совсем хорошо...
Ничего лучше я, к сожалению, не нашел. Другой способ, мне известный, - запускаю top с интервалом обновления 0.2 с и пристально вглядываюсь в быстро мелькающие цифры - весьма неудобен и утомителен.


PM MAIL   Вверх
amg
Дата 13.9.2006, 12:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1145
Регистрация: 3.8.2006
Где: Новосибирск

Репутация: 38
Всего: 50



Цитата(Nab @  12.9.2006,  17:42 Найти цитируемый пост)
... если мне нужно проверять наличие значения как такового, изначально использовал бы хеш ... 
Совершенно согласен, это самое правильное, если заранее знаешь, что будешь проводить поиск.
Цитата
Хотя мои решения с map не такое уж страшное, и как оказалось и в нем есть рациональное зерно
 Еще какое! То, что Ваш вариант с map не использует дополнительную память, может оказаться критическим преимуществом. Почему не использует - буду еще разбираться.
Цитата
PS: amg, а покаж ка, как ты мерял?
Это - уже, см. выше.

Добавлено @ 12:21 
Цитата(Danissimo @  12.9.2006,  17:49 Найти цитируемый пост)
amg, хочу сказать, не удивляйся, что время поиска по хеш-таблице не зависит от количества элементов. Если посмотреть на цели, с которыми разрабатывались хеш-таблицы, то именно эта цель и преследовалась, а именно: время поиска не должно зависеть от количества элементов, то есть должно быть константным. На языке алгоритмического анализа это записывается так: O(n) = const =)) Я не знаю никакой другой структуры данных, у которой алгоритмическая сложность была бы величиной постоянной. Так что все работает, как и должно =)

Спасибо! Буду знать.

Добавлено @ 12:28 
Цитата(korob2001 @  13.9.2006,  03:51 Найти цитируемый пост)
Кстати, amg если будет желаение, можешь попробовать компилировать шаблон только один раз, т.е. добавить модификатор "о" к регулярному выражению.
Спасибо! Попробовал. Есть ускорение, особенно при многократном поиске внутри небольших массивов.

P.S. Прошу у всех прощения за многословие.

PM MAIL   Вверх
Страницы: (3) Все 1 [2] 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl"
korob2001
sharq
  • В этом разделе обсуждаются общие вопросы по языку Perl
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Если ваш вопрос относится к CGI программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", можно скачать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0786 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.