LINUX.ORG.RU

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

 ,


0

1

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

Есть массив

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; 
}

$first = adsp;
$second = adsp;
$third = adsp;
$fourth = adsp;

По идее должно удалить все элементы содержащие хоть половинку(цифру) из рандом выбранного элемента массива. На практике не работает, подскажите в чем моя ошибка?

my @vector = qw(a b c d e f);

sub vec_drop {
	@vector = grep { $_ ne $_[0] } @vector;
}

vec_drop("a"); # => b c d e f
vec_drop("e"); # => b c d f
vec_drop($vector[int rand $#vector]);
joy4eg ★★★★★ ()
Последнее исправление: joy4eg (всего исправлений: 2)
Ответ на: комментарий от balista

А что непонятного то ? Есть массив, и удаляем из него эелементы по значению. Идем в твой код:

$rand = rand @arrset;

Это ошибка. Потому что @arrset в скалярном контексте вернет кол-во элементов в массиве, а не его длинну. И два, rand возвращает float ... Т.е. нужно:

$rand = int rand $#arrset

joy4eg ★★★★★ ()
Ответ на: комментарий от kilolife

удаляет не все элементы.. Мне надо, например, если выбранный случайно элемент содержит 18 и 27(18_27) - удалить все элементами с этими цифрами в начале или конце т.е. и 1_18 и 88_27 и 27_1

balista ()
Ответ на: комментарий от joy4eg

Далее:

$rand_num = $arrset[$rand];

это ОК.
Но потом ...

$arrset = [grep { } @$arrset];

Это тоже ошибка, т.к. у нас есть @arrset = () изначально. А не $arrset = []. Вы уж определитесь ...

joy4eg ★★★★★ ()
Ответ на: комментарий от joy4eg

В вашем примере, можно удалить элемент с уже известным значением. Мне же нужно удалить еще и предполагаемые, я использую для этого регулярное выражение.. Как мне удалить с такими условиями элементы в вашем примере?

balista ()
Ответ на: комментарий от joy4eg

Я не знаю какие элементы в массиве.. У меня нету переменных со значениями все возможных комбинаций с двумя числами.. Мне их надо в массиве найти и удалить зная только два числа. Удалить все элементы, содержащие хотябы одно из этих чисел.

balista ()
Ответ на: комментарий от balista

вот немного переписано:


my @arrset = qw(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 getNum {
  $rand = int rand $#arrset;
  $rand_num = $arrset[$rand];
  $rand_num =~ /^(\d+)_(\d+)$/;
  $buf = $1;
  $buf2 = $2;
  
  
  @arrset = grep {! /(_($buf2|$buf1)$|^($buf2|$buf1)_)/ } @arrset;
  return $rand_num; 
}

$first = getNum;
$second = getNum;
$third = getNum;
$fourth = getNum;
balista ()
Ответ на: комментарий от balista

Пока работает так, что если $first равен 3_21, то $second может равняться 3_30.. т.е. элемент 3_30 - не был удален из массива и был выбран случайно функцией.

balista ()
Ответ на: комментарий от balista
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 = int rand @arrset;
  $rand_num = $arrset[$rand];
  $rand_num =~ /^(\d+)_(\d+)$/;

  @arrset = grep {! /(_($1|$2)$|^($1|$2)_)/ } @arrset;

  return $rand_num;
}
print join ("|", @arrset) . "\n";
print adsp . "\n";
print adsp . "\n";
print adsp . "\n";
print adsp . "\n";
print join ("|", @arrset) . "\n";
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
3_12
9_27
4_13
15_24
1_10|1_19|1_28|5_14|5_23|5_32|6_33|7_16|7_25|7_34|10_19|10_28|14_23|14_32|16_25|16_34|17_26|17_35|18_36|19_28|21_30|22_31|23_32|25_34|26_35|8_17|8_26|8_35

В результирующем массиве нет ничего из 3_12 9_27 4_13 15_24

kilolife ★★★★★ ()
Ответ на: комментарий от kilolife

Большое вам спасибо, я опечаталась просто с именем переменной у себя, действительно нет, заработало, ура!

balista ()

А это обязательное условие, удалить элементы, удовлетворяющие предикату, из исходного массива? По-моему, проще создать новый из тех элементов, которые не удовлетворяют предикату. На Python точно намного проще реализуется.

Virtuos86 ★★★★★ ()
Последнее исправление: Virtuos86 (всего исправлений: 1)
Ответ на: комментарий от Virtuos86

Вот пример, чтобы не быть голословным:

from random import choice

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']
random = choice(arrset).split('_')
res = [i for i in arrset if not filter(lambda rand: rand in i.split('_') , random)]
print random
for i in arrset:
    if i not in res:
        print i,

Virtuos86 ★★★★★ ()
Ответ на: комментарий от Virtuos86

Конечно обязательное) четыре переменные должны иметь свое уникальное значение, не повторяющееся. Да вопрос в общем уже решен, спасибо всем за помощь.

balista ()
Ответ на: комментарий от balista

Можно повыкидывать лишние переменные :)

sub adsp {
  $arrset[int rand @arrset] =~ /^(\d+)_(\d+)$/;
  @arrset = grep {! /(_($1|$2)$|^($1|$2)_)/ } @arrset;
  return "$1_$2";
}

kilolife ★★★★★ ()
Ответ на: комментарий от kilolife

Классно :) только я потом сама свой код через месяц не пойму, пусть будет сложнее, но понятнее))

balista ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.