Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Removing a string-element from an array of strings

by Anonymous Monk
on Jul 25, 2020 at 23:58 UTC ( [id://11119808]=perlquestion: print w/replies, xml ) Need Help??

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I have an array of the form @array = ("AAAA" , "BBBB" , "CCCC" , "DDDD" )
What is a nice way to tell PERL to find the string that matches "BBBB", and remove it from the @array?

Replies are listed 'Best First'.
Re: Removing a string-element from an array of strings
by kcott (Archbishop) on Jul 26, 2020 at 00:25 UTC

    Here's one way:

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

    — Ken

Re: Removing a string-element from an array of strings
by AnomalousMonk (Archbishop) on Jul 26, 2020 at 00:50 UTC

    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:  <%-{-{-{-<

      my %to_remove = map { $_ => 1 } qw( fee fie for ); my @filtered = grep { !$to_remove{$_} } @unfiltered;

      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>

        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

Re: Removing a string-element from an array of strings
by hippo (Bishop) on Jul 26, 2020 at 09:06 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11119808]
Approved by kcott
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (5)
As of 2024-04-25 12:27 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found