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

У меня есть массив, как показано ниже:

my @arr = qw (ram sam ham dam yam fam lam cam) 

Я хочу удалить sam, yam и lam из приведенного выше массива, используя splice. Для этого я использую код ниже:

# first getting the index of sam 
(my  $ind ) = grep {$arr[$_] eq 'sam'} 0 .. $#arr;
splice(@arr, $ind, 1); 

Мой вопрос: поскольку элементы массива изменили свое положение, мне нужно снова получить индекс yam и lam и выполнить соединение массива.

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

Вы действительно настаиваете на использовании splice? Есть какие-то особые причины для этого?

zdim 08.07.2024 06:58

без особой причины, точно так же, как сращивание не оставляет undef в удаленной позиции.

A.G.Progm.Enthusiast 08.07.2024 07:19
my %h = map {$_=>1} qw(sam yam lam); @arr = grep { !defined $h{$_} } @arr; ?
jhnc 08.07.2024 07:29

Что насчет этих элементов делает их «случайными»? На этот вопрос вы получите ответы только на удаление предопределенных элементов, а не случайных элементов.

TLP 08.07.2024 15:53

Я предполагаю, что вы читаете эти данные из файла или чего-то подобного, а не вводите данные, которые через 3 секунды хотите удалить. В этом случае удаление, возможно, следует производить при чтении данных и другим способом.

TLP 08.07.2024 15:58

@TLP они случайны в том смысле, что они не являются последовательными числами, такими как 2,3,4 или 1,2 3 и т. д., поэтому я могу использовать сращивание. Индексы такие, как 2,4,7. Да, элементы предопределены, но их позиции в массиве случайны.

A.G.Progm.Enthusiast 08.07.2024 18:42

@A.G.Progm.Enthusiast Ах, вы имеете в виду случайные индексы, а не случайные элементы. Я бы выбрал выбор, когда вы собираете элементы массива, а не потом.

TLP 08.07.2024 19:43
Структурированный массив Numpy
Структурированный массив Numpy
Однако в реальных проектах я чаще всего имею дело со списками, состоящими из нескольких типов данных. Как мы можем использовать массивы numpy, чтобы...
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
2
7
96
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Если вы знаете значения элементов, которые нужно удалить (sam и т. д. в данном случае), а не индексы, можете сделать

my $re = join '|', map { q(^) . quotemeta . q(\z) } qw(sam yam lam);

my @filtered_ary = grep { not /$re/ } @ary;

или, действительно

my $re = join '|', map { quotemeta } qw(sam yam lam); 
$re = qr/^(?:$re)\z/; 

my @filtered_ary = grep { not /$re/ } @ary;

Также можно перезаписать массив

@ary = grep { ... } @ary

См. quotemeta , которая экранирует «все символы ASCII, не являющиеся словесными», чтобы символы со специальным значением в регулярном выражении можно было использовать в качестве буквальных символов, и qr, создавая регулярное выражение. Использование qr в большинстве случаев не обязательно, но я считаю это хорошей практикой.

Нет необходимости сначала найти индекс, чтобы использовать splice (который вам придется использовать повторно для всех несмежных индексов).


Или, как в jhnc комментарии

my %remove = map { $_ => 1 } qw(sam yam lam); 

@ary = grep { not $remove{$_} } @ary;

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

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

Это точное решение моего требования.

A.G.Progm.Enthusiast 08.07.2024 18:43

@A.G.Progm.Enthusiast Это не так. Он имеет в виду, что если вам нужно удалить индексные номера 2, 3 и 7, вы удаляете их в порядке 7,3,2. Таким образом, удаление индекса не повлияет на другие индексы.

TLP 08.07.2024 19:47

@TLP правильно, но предложенный алгоритм (от самого высокого индекса до самого низкого) справляется со своей задачей.

A.G.Progm.Enthusiast 09.07.2024 06:00

Другие вопросы по теме