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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Уплотнение массива, замена нескольких пустых элементов одним 
:(
    Опции темы
amg
Дата 23.3.2007, 09:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



tishaishii, твой код работает не совсем так, как я имел в виду. Например,
a 0 b 0 0 0 0 0 0 0 0 0 c c 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 d e
превращается в 
a 0 b 0 c c 0 0 0 0 0 0 0 d e
а я хочу получить
a 0 b 0 c c 0 d e
PM MAIL   Вверх
arto
Дата 23.3.2007, 10:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



my ($a,$b) = (0,0); map { defined($_) ? ($a++,$b=0) : ($b++&&splice@a,$a++,1) } @a;
defined($a[0])||splice@a,0,1; defined($a[$#a])||splice@a,$#a,1;
PM MAIL ICQ   Вверх
amg
Дата 23.3.2007, 10:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Первые результаты тестирования.
Относительное время обработки массива:
Код

                     Nab   me    me1
------------------------------------
Разреженный массив   2.0   2.9   1.0
Плотный массив       4.3   6.1   3.0
Для меня оказалось совершенной неожиданностью, что (преобразование массива в строку)-(регулярное выражение)-(обратное преобразование строк в массив) работает быстро.

Код

# Очень мне понравился этот код!
sub Nab {
  my $s;
  return map {if ($_) { $s=0; $_ } else {$s++?():$_}} @_;
}

# Ужасно. Мне стыдно.
sub me {
  my @a = @_;
  my (@b, $curr, $prev);
  $prev = shift @a;
  push @a, '0';
  while (defined($curr = shift @a)) {
    next unless ($prev or $curr);
    push @b, $prev;
    $prev = $curr;
  }
  return @b;
}

# Самое тупое решение. Удивительно, но и самое быстрое.
sub me1 {
  my $s = join ':', @_;
  $s =~ s/(:0){2,}//g;
  return split ':', $s;
}


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


Эксперт
***


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

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



Цитата(arto @  23.3.2007,  10:05 Найти цитируемый пост)
my ($a,$b) = (0,0); map { defined($_) ? ($a++,$b=0) : ($b++&&splice@a,$a++,1) } @a;defined($a[0])||splice@a,0,1; defined($a[$#a])||splice@a,$#a,1;

arto, у меня, к сожалению, не получилось, чтобы твой код выдал то, что я ожидаю. 
Пробовал на массиве 
Код

@a = ('a',undef,undef,undef,undef,undef,undef,'b');


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


Эксперт
***


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

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



Попробовал на реальной задаче (когда элементы массива не одно-, а многосимвольные). Вариант с преобразованием массива в строку здесь здорово проигрывает остальным.
PM MAIL   Вверх
Nab
Дата 23.3.2007, 12:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



ну вот такой уплотненный код для уплотнения массива получился smile

Код

sub compress {
  my $s;
  @_ = map {$_?($s=0 or$_):$s++?():$_} @_;
  $_[0]||shift(@_);
  $_[$#_]||pop(@_);
  return @_
}


Как пустые элементы подразумевается или undef или 0 или строка нулевой длины

Это сообщение отредактировал(а) Nab - 23.3.2007, 12:20


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


Эксперт
***


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

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



да, ошибка была.

sub sq {
    my ($a,$b) = (0,0);
    map { defined($_) ? ($a++,$b=0) : ($b++?splice@_,$a,1:$a++); } @_;
    defined($_[0])||splice@_,0,1; defined($_[$#_])||splice@_,$#_,1;
    return @_;
}

(a,undef,undef,undef,undef,undef,undef,b) =>
 (a,undef,b)

(undef,undef,1,2,3,undef,undef,undef,4,undef,5,undef,undef,6,undef,undef) =>
 (1,2,3,undef,4,undef,5,undef,6)

(undef,undef,a,undef,undef,b,undef) =>
 (a,undef,b)

(undef,undef,a) =>
 (a)

(undef,a,undef) =>
 (a)
PM MAIL ICQ   Вверх
tishaishii
Дата 23.3.2007, 16:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Создатель
***


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

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



Ни какой map и grep по условиям задачи не годится.
Вот пробуй:
Код
BEGIN {$SPACE="\t\r\n0 "}
sub unsignificantChar {+1==length $_[0] && -1!=index $SPACE, $_[0]}
sub trim {
    my($arr, $i, $count)=shift;
    undef while $i<@$arr && &unsignificantChar($arr->[$i++]);
    splice @$arr, 0, --$i;$i--;
    while($i<@$arr) {
        $count++, next if &unsignificantChar($arr->[$i++]);
    splice @$arr, $i-=$count, $count-1 if $count>1;
    $count=0
    }
    splice @$arr, $i-$count
}
my@arr=qw(0 0 a 0 b 0 0 0 0 0 0 0 c c 0 0 0 0 0 0 0 0 0 c c 0 0 0 0 0 0 c c 0 0 d e 0 0);
&trim(\@arr);
print '['.$_.']' foreach @arr;
print "\n"

PM MAIL ICQ Skype   Вверх
arto
Дата 23.3.2007, 16:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



почему?

  DB<1> sub sq { my ($a,$b) = (0,0); map { $_ ? ($a++,$b=0) : ($b++?splice@_,$a,1:$a++); } @_; $_[0]||splice@_,0,1; $_[$#_]||splice@_,$#_,1; return @_; }

  DB<2> @arr=qw(0 0 a 0 b 0 0 0 0 0 0 0 c c 0 0 0 0 0 0 0 0 0 c c 0 0 0 0 0 0 c c 0 0 d e 0 0);

  DB<3> print '['.$_.']' foreach sq (@arr);
[a][0][b][0][c][c][0][c][c][0][c][c][0][d][e]
  DB<4>
PM MAIL ICQ   Вверх
Nab
Дата 23.3.2007, 17:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Я вот тут подумал, что с grep еще красивее получиться может:
Код

sub array_compress {
  my $s;
  @_ = grep {($_&&!($s=0))||!$s++} @_;
  $_[0]||shift(@_);
  $_[$#_]||pop(@_);
  return @_
}



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


Эксперт
***


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

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



в данном случае создается второй массив.
PM MAIL ICQ   Вверх
tishaishii
Дата 23.3.2007, 21:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Создатель
***


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

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



Цитата
почему?

http://forum.vingrad.ru/index.php?showtopi...t&p=1072959
Цитата
обойтись без временного массива

PM MAIL ICQ Skype   Вверх
arto
Дата 23.3.2007, 23:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



my ($a,$b) = (0,0); map { $_ ? ($a++,$b=0) : ($b++?splice@a,$a,1:$a++); } @a; $_[0]||splice@a,0,1; $_[$#_]||splice@a,$#a,1;  -- где временный массив?

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


Опытный
**


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

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



Цитата(arto @  23.3.2007,  19:02 Найти цитируемый пост)
в данном случае создается второй массив.

arto, это ты о чем говорил? об моем варианте или.... ?

А теперь по поводу временных массивов, не думаю что amg, имел ввиду буквально отсутствие временного массива, думаю он больше просил предложить вариант потребляющий меньше ресурсов, как памяти, так и времени....

Цитата(tishaishii @  23.3.2007,  16:15 Найти цитируемый пост)
Ни какой map и grep по условиям задачи не годится.

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

Единственно правильные варианты для splice считаю, while($i < @array) с самостоятельным контролем позиции в массиве. Я это реализовал у себя в первом варианте.

map и grep по большому счету фильтры, которые при этом позволяют обработать по очереди массив имитируя по сути внешний foreach или другой способ организации цикла. Но в большей степени, они могут отфильтровать и вернуть обработанный массив, что очень удобно, я почемуто взялся сразу за map, хотя по идее лучше подходил grep который избавил меня от одного внутреннего условия... Он возвращает елемент в результирующий список только при условии истинности своего выражения, тогда как для map мне пришлось имитировать возврат пустого списка, чтобы елементы не были включены в результирующий набор.

Возможно что и создается второй массив, но он создаеться внутри perl, и думаю вполне оптимально перераспределяется, тогда как использование splice внутри циклов заставляет перл делать еще один внутренний массив, и возможно не один :(... 

А вообще главный тестировщик-оптимизатор у нас amg, вот и попросим его прогнать на достаточно большом и полновесном массиве наши варианты, и по использованию памяти и по времени, пускай выносит результаты в студию...


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


Создатель
***


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

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



Цитата
Хорошо у нас тут удаление элементов, и подозреваю перл грамотно отрабатывает эту ситуацию,

Это python более ли менее грамотно работает с оптимизацией памяти, т.к. везде, где можно неявно использует ссылки, а в Perl - проще, там онного нету.
PM MAIL ICQ Skype   Вверх
Страницы: (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.1367 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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