balista86
@balista86

Как удалить элемент из массива Perl по значению?

Здравствуйте, помогите разобраться с задачей..

Есть массив

my @arrset = ('1_10', '1_19', '1_28', '3_12', '3_21', '3_30', '4_13', '4_22', '4_31', '5_14', '5_23', '5_32', '6_15', '6_24', '6_33', '7_16', '7_25', '7_34', '10_19', '10_28', '12_21', '12_30', '13_22', '13_31', '14_23', '14_32', '15_24', '15_33', '16_25', '16_34', '17_26', '17_35', '18_27', '18_36', '19_28', '21_30', '22_31', '23_32', '24_33', '25_34', '26_35', '27_36', '8_17', '8_26', '8_35', '9_18', '9_27', '9_36');


Есть функция:

sub adsp {
  $rand = rand @arrset;
  $rand_num = $arrset[$rand];
  $rand_num =~ /^(\d+)_(\d+)$/;
  $buf = $1;
  $buf2 = $2;

  $arrset = [grep { /^\d+_$buf$/ } @$arrset];
  $arrset = [grep { /^\d+_$buf2$/ } @$arrset];
  $arrset = [grep { /^${buf}_\d+$/ } @$arrset];
  $arrset = [grep { /^${buf2}_\d+$/ } @$arrset];
  return $rand_num; 
}


По идее должно удалить все элементы содержащие хоть половинку(цифру) из рандом выбранного элемента массива. На практике не работает, подскажите в чем моя ошибка?
  • Вопрос задан
  • 3910 просмотров
Пригласить эксперта
Ответы на вопрос 1
Проблем даже несколько.
Главная -- в grep'ах потерялись отрицания, и получается, что ищем элементы массива, у которых и первая, и вторая половинки равны одновременно и первой, и второй половинке эталонного (случайного) элемента. Таких никогда не находится.

Вторая серьезная проблема: в функции adsp создается ссылка на анонимный массив ($arrset), который не возвращается из функции. Исходный же массив @arrset не модифицируется.

Далее: rand возвращает вещественные числа, использовать их для доступа по индексу в массиве -- странновато (хотя и работает -- вещественные округляются).

И наконец: ни одна переменная в фунции adsp не объявлена (my var), а значит, и use strict в скрипте не используется, т.е. perl не следит за тем, чтобы не использовались необъявленные переменные. В таких случаях обязательно появляются ошибки "присвоили одной переменной, а использовать пытаемся другую".

Итого. По-моему, код должен был быть таким:

sub adsp {
  my $rand = int rand @arrset;
  my $rand_num = $arrset[$rand];
  $rand_num =~ /^(\d+)_(\d+)$/;
  my $buf = $1;
  my $buf2 = $2;

  @arrset = grep { !/^\d+_$buf$/ } @arrset;
  @arrset = grep { !/^\d+_$buf2$/ } @arrset;
  @arrset = grep { !/^${buf}_\d+$/ } @arrset;
  @arrset = grep { !/^${buf2}_\d+$/ } @arrset;
  return $rand_num; 
}


Случайные индекс берется целый, модифицируется исходный массив @arrset, в grep'ах условия с отрицанием, все переменные объявлены лексическими (my).

И обязательно используйте в каждом скрипте
use strict;
use warnings;

-- это экономит много времени на отладке.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы