http://qs321.pair.com?node_id=11119811


in reply to Removing a string-element from an array of strings

The next step: How do you remove any array element that exactly matches any of 'fee' 'fie' 'foe'?

c:\@Work\Perl\monks>perl -wMstrict -le "my @ra = qw(foo fee efie fiee efiee foe fum); print qq{before: (@ra)}; ;; my $rx_fee_fie_foe = qr{ \A f [eio] e \z }xms; ;; @ra = grep !m{ $rx_fee_fie_foe }xms, @ra; print qq{after: (@ra)}; " before: (foo fee efie fiee efiee foe fum) after: (foo efie fiee efiee fum)
Question: How would you remove all array elements that match the above pattern anywhere in the string, so that the final output will be foo fum?

Please see perlre, perlretut, and perlrequick.


Give a man a fish:  <%-{-{-{-<

Replies are listed 'Best First'.
Re^2: Removing a string-element from an array of strings
by ikegami (Patriarch) on Jul 27, 2020 at 09:37 UTC
    my %to_remove = map { $_ => 1 } qw( fee fie for ); my @filtered = grep { !$to_remove{$_} } @unfiltered;
Re^2: Removing a string-element from an array of strings
by Anonymous Monk on Jul 26, 2020 at 16:31 UTC

    Here is what I am after:

    @history = ( "Cache::SizeAwareMemoryCache(3)" , "dhcp-options(5)" , "B +N_add_word(3)" , "audit-packages(8)" ) $choice = "dhcp-options(5)"
    Find the value of choice in the array "@history", remove it, and cat it to the end of the array.

    I found an example that works on an array with the form @array = ( "aaaa" , "bbbb" , "cccc" , "dddd" ), but it refuses to work for my @history array ( the parens in the string(s) ? ) Notice all the elements are in char-string format -- thats that I indended to say. Since the first element contains "::", will that be of any consequence?

    Sorry for the confusion

      I found an example that works on an array with the form @array = ( "aaaa" , "bbbb" , "cccc" , "dddd" ), but it refuses to work for my @history array ( the parens in the string(s) ? )

      Impossible to say. You've provided no code to examine.

      Here's something that may work IIUC your requirements:

      c:\@Work\Perl\monks>perl -wMstrict -le "use List::MoreUtils qw(part); ;; my @history = qw(Cache::SizeAwareMemoryCache(3) dhcp-options(5) BN_ad +d_word(3) audit-packages(8)); my $choice = 'dhcp-options(5)'; print qq{before: (@history)}; ;; @history = map @$_, part { $_ ne $choice ? 0 : 1 } @history; print qq{after: (@history)}; " before: (Cache::SizeAwareMemoryCache(3) dhcp-options(5) BN_add_word(3) + audit-packages(8)) after: (Cache::SizeAwareMemoryCache(3) BN_add_word(3) audit-packages( +8) dhcp-options(5))
      Note that this will remove and append all matching strings to the end of the array, not just the first one. See List::MoreUtils::part().

      WRT this comment by LanX which I just saw, note that the solution above uses exact string comparison, not regex comparison. If you're using regexes, the approach must be slightly different.


      Give a man a fish:  <%-{-{-{-<

      You can also use the stable sort, sorting by whether the string equals the choice. The ones that don't will be sorted as zeroes, i.e. at the beginning of the list, the one that does will be sorted as 1, i.e. will go to the end of the list.
      #!/usr/bin/perl use warnings; use strict; use feature qw{ say }; use sort 'stable'; use List::UtilsBy qw{ sort_by }; my @history = ( 'Cache::SizeAwareMemoryCache(3)' , 'dhcp-options(5)' , + 'BN_add_word(3)' , 'audit-packages(8)' ); my $choice = 'dhcp-options(5)'; @history = sort_by { $_ eq $choice } @history; say "@history";

      map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
      This seems to be a continuation of the thread about parsing man pages. (HELP! I am in regex-hell)

      Your post is hard to read because of missing <code> tags!

      (If you had logged in you'd be capable to edit and fix it.)

      Anyway my guess is that you need quotemeta resp. \Q because parens () are metacharacters in regexes, which need to be escaped.

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery

      As LanX said, you need to use quotemeta(or \Q) for the parentheses.

      Here might be what you want.

      #!/usr/bin/perl use strict; use warnings; my @history = ( "Cache::SizeAwareMemoryCache(3)" , "dhcp-options(5)" , + "BN_add_word(3)" , "audit-packages(8)" ); my $choice = "dhcp-options(5)"; @history = grep !/\Q$choice\E/, @history; # '\Q' to quotemeta push @history, $choice; print "@history";
      Prints:

      C:\Old_Data\perlp>perl test3.pl Cache::SizeAwareMemoryCache(3) BN_add_word(3) audit-packages(8) dhcp-o +ptions(5) C:\Old_Data\perlp>
        push @history, $choice;

        What if the $choice was not found in the @history array?


        Give a man a fish:  <%-{-{-{-<

      Here's another approach if you're looking for an exact string match for one of multiple choices:

      c:\@Work\Perl\monks>perl -wMstrict -le "use List::MoreUtils qw(part); ;; my @history = qw(Foo::End(3) dhcp-options(5) Back_word(3) audit-packa +ges(8)); print qq{before: (@history)}; ;; my %choices = map { $_ => 1 } qw(Back_word(3) Foo::End(3)); ;; @history = map @$_, part { exists $choices{$_} } @history; print qq{after: (@history)}; " before: (Foo::End(3) dhcp-options(5) Back_word(3) audit-packages(8)) after: (dhcp-options(5) audit-packages(8) Foo::End(3) Back_word(3))


      Give a man a fish:  <%-{-{-{-<

      Treating your code as some sort of sentient entity which "refuses to work" will get you nowhere. Your code is no doubt doing exactly what you asked it to do; the problem will be what you asked.

      If you do not show your code, along with its output which may consist solely of some error message, we cannot help you! Please read "How do I post a question effectively?" and SSCCE; then provide us with something that we can use to help you.

      Your requirements have changed. You now additionally want "... and cat it to the end of the array."; however, you don't say what happens if the element to be removed doesn't exist.

      There are a lot posts involving regexes. Based on what you've told us so far, I see no need for the overhead of firing up the regex engine.

      I originally provided:

      $ perl -E 'my @x = qw{A B C D}; @x = grep $_ ne "B", @x; say "@x"' A C D

      With your new additional requirement, you could code:

      $ perl -E 'my @x = qw{A B C D}; my $y = "B"; @x = (grep($_ ne $y, @x), + $y); say "@x"' A C D B

      If "B" is not found, you perhaps want

      $ perl -E 'my @x = qw{A B C D}; my $y = "Z"; @x = (grep($_ ne $y, @x), + $y); say "@x"' A B C D Z

      or

      $ perl -E 'my @x = qw{A B C D}; my $y = "Z"; @x = (grep($_ ne $y, @x), + $y)[0..$#x]; say "@x"' A B C D

      Which still works if "B" is found:

      $ perl -E 'my @x = qw{A B C D}; my $y = "B"; @x = (grep($_ ne $y, @x), + $y)[0..$#x]; say "@x"' A C D B

      Because these methods simply use string inequality (ne) you won't encounter problems with characters being special to a regular expression:

      $ perl -E 'my @history = qw{Cache::SizeAwareMemoryCache(3) dhcp-option +s(5) BN_add_word(3) audit-packages(8)}; my $choice = "dhcp-options(5) +"; @history = (grep($_ ne $choice, @history), $choice); say "@history +"' Cache::SizeAwareMemoryCache(3) BN_add_word(3) audit-packages(8) dhcp-o +ptions(5) $ perl -E 'my @history = qw{Cache::SizeAwareMemoryCache(3) dhcp-option +s(5) BN_add_word(3) audit-packages(8)}; my $choice = "not-found(0)"; +@history = (grep($_ ne $choice, @history), $choice); say "@history"' Cache::SizeAwareMemoryCache(3) dhcp-options(5) BN_add_word(3) audit-pa +ckages(8) not-found(0) $ perl -E 'my @history = qw{Cache::SizeAwareMemoryCache(3) dhcp-option +s(5) BN_add_word(3) audit-packages(8)}; my $choice = "dhcp-options(5) +"; @history = (grep($_ ne $choice, @history), $choice)[0..$#history]; + say "@history"' Cache::SizeAwareMemoryCache(3) BN_add_word(3) audit-packages(8) dhcp-o +ptions(5) $ perl -E 'my @history = qw{Cache::SizeAwareMemoryCache(3) dhcp-option +s(5) BN_add_word(3) audit-packages(8)}; my $choice = "not-found(0)"; +@history = (grep($_ ne $choice, @history), $choice)[0..$#history]; sa +y "@history"' Cache::SizeAwareMemoryCache(3) dhcp-options(5) BN_add_word(3) audit-pa +ckages(8)

      — Ken