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

Поиск:

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


Эксперт
***


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

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



Нужно проделать с массивом то, что обычно делают со строками:
Код

s/^\s+//; # Удаляем пустые элементы в начале
s/\s+$//; # Удаляем пустые элементы в конце
s/\s+/ /g; # Заменяем каждую последовательность пустых элементов одним

Конечно, какой-то работающий код для массива у меня есть. Но, как обычно, интересует эффективность, в частности, можно ли обойтись без временного массива.
PM MAIL   Вверх
arto
Дата 22.3.2007, 12:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



grep или map со splice
PM MAIL ICQ   Вверх
tishaishii
Дата 22.3.2007, 13:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Не удастся с grep. grep возвращает массив.
Надо splice и for или while.
Код
sub xgrep(&@) {
    my($sub, $arr, $size, $j, $i)=(shift, $_[0], (scalar @{+shift}) x 2, 0);
    while($j>0 && $i<$size) {
        splice @$arr, $i--, 1 unless $sub->($arr->[$i]);
        $i++;
        $j--
    }
    +$arr
}

my@arr=1..20;
xgrep{$_[0]>5 && $_[0]<10}\@arr;
print join "\n", @arr;


Это сообщение отредактировал(а) tishaishii - 22.3.2007, 13:31
PM MAIL ICQ Skype   Вверх
arto
Дата 22.3.2007, 13:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



my $a = 0; grep { defined ($_) ? $a++ : splice @a,$a,1 } @a
PM MAIL ICQ   Вверх
Nab
Дата 22.3.2007, 13:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Можно вот так вот:
Код

my ($i, $space) = (0,0);
# пока не достигли конца массива
while ($i < @array) {
  # если елемент пустой
  if (@array[$i++]) {
    # если предыдущие были пустыми елементами, то мы их удаляем
    if ($space) {
      # откатываем индекс
      $i -= $space;
      # удаляем пустые елементы
      splice @array, $i, $space;
      # обнуляем счетчик пустых елементов
      $space = 0
    }
  } else {
    # здесь мы будем если у нас пустой елемент, 
    # мы его пропускаем, но увеличиваем счетчик...
    # чтоб обработать впоследствии
    $space++;
  }
}
# а здесь мы удаляем если в конце массива у нас пустые есть, мы то уже из цикла вышли по окончании индекса
splice @array, $i - $space, $space if $space;

Отличие то что позволяет за один раз удалить несколько елементов... не вызывая splice каждому...

Писал прям в форум. но надеюсь понятно будет, возможно я не учел то что надо один оставлять пустой, но надеюсь сам сможешь исправить...


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


Эксперт
***


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

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



arto, твой код просто удаляет все пустые элементы, а это не совсем то, что нужно.
PM MAIL   Вверх
Nab
Дата 22.3.2007, 14:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Проверил, работает:
Код

@array = map {if ($_) { $s=0; $_ } else {$s++?():$_}} @array;



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


Эксперт
***


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

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



"Нужно проделать с массивом то, что обычно делают со строками:
s/^\s+//; # Удаляем пустые элементы в начале" -- ?
PM MAIL ICQ   Вверх
Nab
Дата 22.3.2007, 14:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



arto, не придирайся, smile то в начале, но не везде, да и мой код тогда неверен...
нужно тогда как для строк, три строки:
Код

# уплотняем все пустые
@array = map {if ($_) { $s=0; $_ } else {$s++?():$_}} @array;
# удаляем лидирующий, если есть
shift(@array) unless $array[0];
# и завершающий....
pop(@array) unless $array[$#array];

думаю так лучше всего будет


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


Эксперт
***


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

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



так что удалять-то надо?
PM MAIL ICQ   Вверх
Nab
Дата 22.3.2007, 14:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(arto @  22.3.2007,  14:31 Найти цитируемый пост)
так что удалять-то надо?

Ну дык все просто, удаляем лидирующие пустые елементы и завершающие, внутри, если несколько подряд идущих, заменяем одним...



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


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


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

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



Что-то не видно оно.
Вот
Код
BEGIN {$SPACE="\t\r\n "}
sub unsignificantChar {+1==length $_[0] && -1!=index $SPACE, $_[0]}
sub trim {
    my($size, $arr, $i, $j)=(scalar @{$_[0]}, shift);
    for(($bool, $i)=1; $i<$size && $bool; $i++) {
        last unless &unsignificantChar($arr->[$i]);
        $arr->[$i]=()
    }
    for($j=$size-1; $j>$i; $j--) {
        last unless &unsignificantChar($arr->[$j]);
        $arr->[$j]=()
    }
}

my@arr=("\n", "\n", "\n", 1, 2, 3, "\n", "\n", "\n");
&trim(\@arr);
print '[', @arr, ']';

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


Опытный
**


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

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



Тут, думаю стоит уточнить, что имеется ввиду под "пустым" элементом. Пробельные символы, определенность елемента, или еще что, и уже подставлять необходимое сравнение в наши варианты...


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


Эксперт
***


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

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



Цитата(Nab @  22.3.2007,  15:08 Найти цитируемый пост)
Тут, думаю стоит уточнить, что имеется ввиду под "пустым" элементом. 
Подойдет что угодно. Предлагаю для опреленности считать пустым элементом массива элемент, состоящий из символа "0" (ноль). Предлагаю также считать, что ведущих и ведомых нулей в массиве нет (их удалить несложно). Т.е., например, из 
('a', '0', 'b', '0', '0', 'c', '0', '0', '0', 'd')
должно получиться
('a', '0', 'b', '0', 'c', '0', 'd')

ЗЫ Господа! Примеры кода появляются быстрее, чем я успеваю в них разобраться, так что не обессудьте, сравнивать буду уже только завтра (а то у нас в Новосибирске дело к ночи).

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


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


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

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



Таак.
Что-то мне уже кажется, что надо удалять "пустые символы" не только по краям, но и везде, в середине удалять дубликаты?
Ну так задача гораздо упрощается.
Код
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) {
        if(&unsignificantChar($arr->[$i++])) {
            $count++
        } else {
            splice @$arr, $i---$count, $count-1 if $count>1;
            $count=0
        }
    }
    splice @$arr, $i-$count
}
my@arr=qw(0 0 0 1 0 3 2 0 0 3 0);
&trim(\@arr);
print map{'['.$_.']'}@arr;


Это сообщение отредактировал(а) tishaishii - 23.3.2007, 01:20
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.0558 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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