grepping a list of patterns in a larger list

Discussion in 'Perl Misc' started by Udaykumar Kunapuli, May 6, 2014.

  1. Hi,

    I have 2 lists.

    As an example:
    @list1 = (1234, 345638, 3535, 93756387);
    @list2 = ("375539 Linux DONE", "1234 Linux DONE", "345638 Linux EXIT", "6384643 Linux RUN", "45234 Linux RUN", "3535 Linux DONE", "93756387 Linux DONE");

    I need to print out the list of elements in list2 where the first number part of the string does NOT exist in list1.

    I need to get a list3 from list2 where list3 looks like below
    @list3 = ("375539 Linux DONE", "6384643 Linux RUN", "45234 Linux RUN");

    None of the above first number parts in list3 exist in list1, which is how I want it to be.

    What would be the simplest way of doing this in Perl?

    Thanks,
    Uday
    Udaykumar Kunapuli, May 6, 2014
    #1
    1. Advertising

  2. Udaykumar Kunapuli

    $Bill Guest

    On 5/5/2014 20:17, Udaykumar Kunapuli wrote:
    > Hi,
    >
    > I have 2 lists.
    >
    > As an example:
    > @list1 = (1234, 345638, 3535, 93756387);
    > @list2 = ("375539 Linux DONE", "1234 Linux DONE", "345638 Linux EXIT", "6384643 Linux RUN", "45234 Linux RUN", "3535 Linux DONE", "93756387 Linux DONE");
    >
    > I need to print out the list of elements in list2 where the first number part of the string does NOT exist in list1.
    >
    > I need to get a list3 from list2 where list3 looks like below
    > @list3 = ("375539 Linux DONE", "6384643 Linux RUN", "45234 Linux RUN");
    >
    > None of the above first number parts in list3 exist in list1, which is how I want it to be.
    >
    > What would be the simplest way of doing this in Perl?


    If list1 is reasonably small, I'd just grep list2 for each item in list1:

    use strict;
    use warnings;

    my @list1 = (1234, 345638, 3535, 93756387);
    my @list2 = ("375539 Linux DONE", "1234 Linux DONE", "345638 Linux EXIT",
    "6384643 Linux RUN", "45234 Linux RUN", "3535 Linux DONE",
    "93756387 Linux DONE"
    );

    foreach my $re (@list1) {
    my @found = grep /$re/, @list2;
    print "@found\n" if @found;
    }

    __END__
    $Bill, May 6, 2014
    #2
    1. Advertising

  3. Udaykumar Kunapuli

    Tim McDaniel Guest

    In article <>,
    Udaykumar Kunapuli <> wrote:
    >I have 2 lists.
    >
    >As an example:
    >@list1 = (1234, 345638, 3535, 93756387);
    >@list2 = ("375539 Linux DONE", "1234 Linux DONE", "345638 Linux EXIT", "6384643 Linux RUN", "45234 Linux
    >RUN", "3535 Linux DONE", "93756387 Linux DONE");
    >
    >I need to print out the list of elements in list2 where the first number part of the string does NOT
    >exist in list1.
    >
    >I need to get a list3 from list2 where list3 looks like below
    >@list3 = ("375539 Linux DONE", "6384643 Linux RUN", "45234 Linux RUN");
    >
    >None of the above first number parts in list3 exist in list1, which is how I want it to be.
    >
    >What would be the simplest way of doing this in Perl?


    The better sort of reply would note that this might be a "do my
    homework for me" question and would ask what you've tried already.

    So what have you tried already? Or what have you thought about and
    not known how to do?

    I'll be kind enough, or unkind enough (in that, if it's a class,
    someone providing you with a solution is hurting your learning), to
    suggest that you consider a hash table:
    - hash1, with key = each element of @list1 and value = 1 (the value
    need not be used so it doesn't matter)
    Then go through each element of @list2, separate out the number at the
    start of the element, and see whether it's in %hash1.

    --
    Tim McDaniel,
    Tim McDaniel, May 6, 2014
    #3
  4. Udaykumar Kunapuli

    gamo Guest

    El 06/05/14 05:17, Udaykumar Kunapuli escribió:
    > Hi,
    >
    > I have 2 lists.
    >
    > As an example:
    > @list1 = (1234, 345638, 3535, 93756387);
    > @list2 = ("375539 Linux DONE", "1234 Linux DONE", "345638 Linux EXIT", "6384643 Linux RUN",


    "45234 Linux RUN", "3535 Linux DONE", "93756387 Linux DONE");
    >
    > I need to print out the list of elements in list2 where the first number part of the string does NOT exist in list1.
    >
    > I need to get a list3 from list2 where list3 looks like below
    > @list3 = ("375539 Linux DONE", "6384643 Linux RUN", "45234 Linux RUN");
    >
    > None of the above first number parts in list3 exist in list1, which is how I want it to be.
    >
    > What would be the simplest way of doing this in Perl?
    >
    > Thanks,
    > Uday
    >


    for $j (@list2){
    $j =~ /(\d+)\s/;
    $n = $1; # extract the number
    $ok=1;
    for $i (@list1){
    if ($i == $n){
    $ok =0;
    last;
    }
    }
    if ($ok==1){
    push @list3, $j;
    }
    }

    You ask for the simplest way.

    --
    http://www.telecable.es/personales/gamo/
    gamo, May 6, 2014
    #4
  5. Udaykumar Kunapuli

    ilovelinux Guest

    Maybe not the simplest, but to avoid programming a nested loop: create a
    regular expression of the numbers in @list1 and grep @list2 for that RE.

    my $re = join("|", map { quotemeta $_ } @list1);
    my @list3 = grep { !/$re/ } @list2;
    ilovelinux, May 6, 2014
    #5
  6. Udaykumar Kunapuli

    gamo Guest

    El 06/05/14 10:08, Jürgen Exner escribió:
    > gamo <> wrote:
    >> El 06/05/14 05:17, Udaykumar Kunapuli escribió:
    >>> Hi,
    >>>
    >>> I have 2 lists.
    >>>
    >>> As an example:
    >>> @list1 = (1234, 345638, 3535, 93756387);
    >>> @list2 = ("375539 Linux DONE", "1234 Linux DONE", "345638 Linux EXIT", "6384643 Linux RUN",

    >>
    >> "45234 Linux RUN", "3535 Linux DONE", "93756387 Linux DONE");
    >>>
    >>> I need to print out the list of elements in list2 where the first number part of the string does NOT exist in list1.
    >>>
    >>> I need to get a list3 from list2 where list3 looks like below
    >>> @list3 = ("375539 Linux DONE", "6384643 Linux RUN", "45234 Linux RUN");
    >>>
    >>> None of the above first number parts in list3 exist in list1, which is how I want it to be.
    >>>
    >>> What would be the simplest way of doing this in Perl?
    >>>
    >>> Thanks,
    >>> Uday
    >>>

    >>
    >> for $j (@list2){
    >> $j =~ /(\d+)\s/;
    >> $n = $1; # extract the number
    >> $ok=1;
    >> for $i (@list1){
    >> if ($i == $n){
    >> $ok =0;
    >> last;
    >> }
    >> }
    >> if ($ok==1){
    >> push @list3, $j;
    >> }
    >> }
    >>
    >> You ask for the simplest way.

    >
    > The simplest way is to use "exists" instead of that flag in a nested
    > loop.
    >
    > jue
    >


    Ok, let's go:

    for $i (@list1){
    $h{$i}=1;
    }

    for $j (@list2){
    $j =~ /(\d+)\s/;
    $n = $1;
    unless (defined $h{$n}){
    push @list3, $j;
    }
    }
    %h = ();


    --
    http://www.telecable.es/personales/gamo/
    gamo, May 6, 2014
    #6
  7. gamo <> writes:
    > El 06/05/14 10:08, Jürgen Exner escribió:
    >> gamo <> wrote:
    >>> El 06/05/14 05:17, Udaykumar Kunapuli escribió:
    >>>> Hi,
    >>>>
    >>>> I have 2 lists.
    >>>>
    >>>> As an example:
    >>>> @list1 = (1234, 345638, 3535, 93756387);
    >>>> @list2 = ("375539 Linux DONE", "1234 Linux DONE", "345638 Linux EXIT", "6384643 Linux RUN",
    >>>
    >>> "45234 Linux RUN", "3535 Linux DONE", "93756387 Linux DONE");
    >>>>
    >>>> I need to print out the list of elements in list2 where the first number part of the string does NOT exist in list1.


    [...]

    >> The simplest way is to use "exists" instead of that flag in a nested
    >> loop.
    >>
    >> jue
    >>

    >
    > Ok, let's go:
    >
    > for $i (@list1){
    > $h{$i}=1;
    > }
    >
    > for $j (@list2){
    > $j =~ /(\d+)\s/;
    > $n = $1;
    > unless (defined $h{$n}){
    > push @list3, $j;
    > }
    > }
    > %h = ();


    This can be simplified somewhat with map and grep:

    %filter = map { $_, 1 } @list1;
    @list3 = grep { /^(\S+)/, !$filter{$1}; } @list2;

    The grep expression could also be written as

    !$first{(/^(\S+)/)[0]}

    I'm unsure if this should be considered a good or a bad idea.
    Rainer Weikusat, May 6, 2014
    #7
  8. Udaykumar Kunapuli

    Manfred Lotz Guest

    On Mon, 5 May 2014 20:17:05 -0700 (PDT)
    Udaykumar Kunapuli <> wrote:

    > Hi,
    >
    > I have 2 lists.
    >
    > As an example:
    > @list1 = (1234, 345638, 3535, 93756387);
    > @list2 = ("375539 Linux DONE", "1234 Linux DONE", "345638 Linux
    > EXIT", "6384643 Linux RUN", "45234 Linux RUN", "3535 Linux DONE",
    > "93756387 Linux DONE");
    >
    > I need to print out the list of elements in list2 where the first
    > number part of the string does NOT exist in list1.
    >
    > I need to get a list3 from list2 where list3 looks like below
    > @list3 = ("375539 Linux DONE", "6384643 Linux RUN", "45234 Linux
    > RUN");
    >
    > None of the above first number parts in list3 exist in list1, which
    > is how I want it to be.
    >
    > What would be the simplest way of doing this in Perl?
    >


    I would do it this way. If @list1 is really large one should perhaps
    think twice.

    <---------------------------snip------------------------------>
    #! /usr/bin/perl

    use strict;
    use warnings;

    my @list1 = (1234, 345638, 3535, 93756387);
    my @list2 = ("375539 Linux DONE", "1234 Linux DONE", "345638 Linux
    EXIT", "6384643 Linux RUN", "45234 Linux RUN", "3535 Linux DONE",
    "93756387 Linux DONE");


    my %hash = map { $_ => 1 } @list1;
    my @list3;

    foreach my $li ( @list2 ) {
    my @words = split /\s+/,$li;
    if ( not defined $hash{"$words[0]"} ) {
    push @list3, $li;
    }
    }

    foreach my $li ( @list3 ) {
    print "$li\n";
    }

    <---------------------------snap------------------------------>
    Manfred Lotz, May 6, 2014
    #8
  9. Udaykumar Kunapuli

    Tim McDaniel Guest

    In article <lkaa9n$vvq$>, gamo <> wrote:
    >for $i (@list1){
    > $h{$i}=1;
    >}


    People should
    use strict;
    use warnings;
    and declare all variables.

    People have posted two ways to convert a list to a hash in which the
    indexes are the members of the list. Here's the version I usually use:

    @h{@list1} = (1) x @list1;

    --
    Tim McDaniel,
    Tim McDaniel, May 6, 2014
    #9
  10. Udaykumar Kunapuli

    Tim McDaniel Guest

    In article <lkbai0$2qj$>,
    Tim McDaniel <> wrote:
    >People have posted two ways to convert a list to a hash in which the
    >indexes are the members of the list.


    Sorry -- two people, both using something of the form
    %hash1 = map { $_ => 1 } @list1;

    --
    Tim McDaniel,
    Tim McDaniel, May 6, 2014
    #10
  11. (Tim McDaniel) writes:
    > In article <lkaa9n$vvq$>, gamo <> wrote:
    >>for $i (@list1){
    >> $h{$i}=1;
    >>}

    >
    > People should
    > use strict;
    > use warnings;
    > and declare all variables.
    >
    > People have posted two ways to convert a list to a hash in which the
    > indexes are the members of the list. Here's the version I usually use:
    >
    > @h{@list1} = (1) x @list1;


    Two similar other ways would be

    ++$_ for @h{@list}

    s///1/ for @h{@list}

    If one is willing to test for 'existence' instead of truth, any
    expression can be used in front of the find, eg

    // for @h{@list}

    or

    1 for @h{@list}

    Actually, any operator which modifies its operand will do for this case, eg,

    ++@h{@list}
    Rainer Weikusat, May 6, 2014
    #11
  12. Udaykumar Kunapuli

    Tim McDaniel Guest

    In article <>,
    Rainer Weikusat <> wrote:
    > (Tim McDaniel) writes:
    >> ... to convert a list to a hash in which the
    >> indexes are the members of the list.

    >
    >If one is willing to test for 'existence' instead of truth, any
    >expression can be used in front of the find, eg

    ....
    >1 for @h{@list}
    >
    >Actually, any operator which modifies its operand will do for this case, eg,
    >
    >++@h{@list}


    $ perl -e 'use strict; use warnings; use Data::Dumper; my @list = (17, 19, 23); my %h; ++@h{@list}; print Dumper(\%h), "\n"'
    $VAR1 = {
    '23' => 1,
    '19' => undef,
    '17' => undef
    };
    $ perl -e 'use strict; use warnings; use Data::Dumper; my @list = (17, 19, 23); my %h; 0 for @h{@list}; print Dumper(\%h), "\n"'
    $VAR1 = {
    '23' => undef,
    '19' => undef,
    '17' => undef
    };

    OK, I don't get it. What's going on here? I don't think it could be
    autovivication eo nomine.

    --
    Tim McDaniel,
    Tim McDaniel, May 6, 2014
    #12
  13. (Tim McDaniel) writes:
    > Rainer Weikusat <> wrote:
    >> (Tim McDaniel) writes:
    >>> ... to convert a list to a hash in which the
    >>> indexes are the members of the list.

    >>
    >>If one is willing to test for 'existence' instead of truth, any
    >>expression can be used in front of the find, eg

    > ...
    >>1 for @h{@list}
    >>
    >>Actually, any operator which modifies its operand will do for this case, eg,
    >>
    >>++@h{@list}

    >
    > $ perl -e 'use strict; use warnings; use Data::Dumper; my @list = (17, 19, 23); my %h; ++@h{@list}; print Dumper(\%h), "\n"'
    > $VAR1 = {
    > '23' => 1,
    > '19' => undef,
    > '17' => undef
    > };
    > $ perl -e 'use strict; use warnings; use Data::Dumper; my @list = (17, 19, 23); my %h; 0 for @h{@list}; print Dumper(\%h), "\n"'
    > $VAR1 = {
    > '23' => undef,
    > '19' => undef,
    > '17' => undef
    > };
    >
    > OK, I don't get it. What's going on here? I don't think it could be
    > autovivication eo nomine.


    'Autovivification because of lvalue context', see pp_hslice in pp.c.
    Rainer Weikusat, May 6, 2014
    #13
  14. Udaykumar Kunapuli

    Dr.Ruud Guest

    On 2014-05-06 05:17, Udaykumar Kunapuli wrote:

    > I have 2 lists.
    >
    > As an example:
    > @list1 = (1234, 345638, 3535, 93756387);
    > @list2 = ("375539 Linux DONE", "1234 Linux DONE", "345638 Linux EXIT", "6384643 Linux RUN", "45234 Linux RUN", "3535 Linux DONE", "93756387 Linux DONE");
    >
    > I need to print out the list of elements in list2 where the first number part of the string does NOT exist in list1.
    >
    > I need to get a list3 from list2 where list3 looks like below
    > @list3 = ("375539 Linux DONE", "6384643 Linux RUN", "45234 Linux RUN");
    >
    > None of the above first number parts in list3 exist in list1, which is how I want it to be.
    >
    > What would be the simplest way of doing this in Perl?


    There are many ways, for example:

    perl -Mstrict -wE'
    my @list1 = (1234, 345638, 3535, 93756387);
    my @list2 = ("375539 Linux DONE", "1234 Linux DONE"
    , "345638 Linux EXIT", "6384643 Linux RUN", "45234 Linux RUN"
    , "3535 Linux DONE", "93756387 Linux DONE");
    my $re = join "|", @list1;
    my @list3 = grep !/^(?:$re)\b/, @list2;
    '

    --
    Ruud
    Dr.Ruud, May 13, 2014
    #14
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Bryan Krone

    perl efficiency -- fastest grepping?

    Bryan Krone, Nov 5, 2004, in forum: Perl
    Replies:
    1
    Views:
    1,464
    Jim Gibson
    Nov 8, 2004
  2. Peter Williams
    Replies:
    1
    Views:
    1,358
    Dylan Parry
    Jun 3, 2005
  3. John Fitzsimons

    Grepping with Python - script/prog required.

    John Fitzsimons, Jun 24, 2003, in forum: Python
    Replies:
    1
    Views:
    728
    John Fitzsimons
    Jul 1, 2003
  4. David A. Black

    [ANN] Grepper: object-oriented grepping

    David A. Black, Dec 24, 2008, in forum: Ruby
    Replies:
    1
    Views:
    121
    Tiago Nogueira
    Dec 24, 2008
  5. David A. Black
    Replies:
    3
    Views:
    106
    Florian Gilcher
    Jan 19, 2009
Loading...

Share This Page