J
J
Julia2014-06-07 13:10:06
Perl
Julia, 2014-06-07 13:10:06

How to remove an element from a Perl array by value?

Hello, help me figure out the problem ..
There is an array

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');

There is a function:
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; 
}

In theory, it should remove all elements containing at least a half (number) from a randomly selected element of the array. In practice, it does not work, tell me what is my mistake?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
E
Elena Bolshakova, 2014-06-29
@liruoko

There are even several problems.
The main thing is that negations are lost in greps, and it turns out that we are looking for array elements in which both the first and second halves are simultaneously equal to both the first and second half of the reference (random) element. These are never found.
The second major problem is that the adsp function creates a reference to an anonymous array ($arrset) that is not returned from the function. The original @arrset array is not modified.
Further: rand returns real numbers, using them to access by index in an array is strange (although it works - real numbers are rounded).
And finally: not a single variable is declared in the adsp function (my var), which means that use strict is not used in the script, i.e. perl does not ensure that undeclared variables are not used. In such cases, errors "assigned to one variable, but trying to use another" always appear.
Total. I think the code should have been like this:

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

A random index is taken as an integer, the original @arrset array is modified, conditions are negated in greps, all variables are declared lexical (my).
And be sure to use in every script
use strict;
use warnings;

-- this saves a lot of debugging time.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question