Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation

Unique key identifer?

by lecb (Acolyte)
on Jun 27, 2014 at 17:42 UTC ( #1091498=perlquestion: print w/replies, xml ) Need Help??
lecb has asked for the wisdom of the Perl Monks concerning the following question:

Good evening Monks!
I am struggling to deal with a case when a hash key has two values. I have written a basic program to try and illustrate what I am trying to do.

apple cherry peach banana cherry
apple + cherry - cherry + peach + banana -
Using the fruit.txt file, I would like to be able to print 'cherry' if it is matched as positive, as well as if it is negative. Is there anyway I can do this in perl?
My program:
#!/usr/bin/perl -w use strict; use Data::Dumper; my $inputfile1 = $ARGV[0]; my $inputfile2 = $ARGV[1]; open (FILE1, $inputfile1) or die; open (FILE2, $inputfile2) or die; my @fruit = <FILE1>; # fruit.txt close FILE1; my @strands = <FILE2>; ## strands.txt close FILE2; my (@fruitcolumn, @strand_direction, %strands, $key, $value); foreach my $line(@strands) { my @colsplit = split("\t", $line); push (@fruitcolumn, $colsplit[0]); push (@strand_direction, $colsplit[1]); } s/\s+$// foreach @strand_direction; s/\s+$// foreach @fruit; while ($key = shift (@fruitcolumn)) { $value = shift (@strand_direction); push @{$strands{$key}}, $value; } foreach my $line (@fruit) { if ($strands{$line} =~ m/\+/) { print "my positives are $line", "\n"; } elsif($strands{$line} =~ m/\-/) { print "my negatives are $line", "\n"; } }
Any help would be gratefully received. - E

Replies are listed 'Best First'.
Re: Unique key identifer?
by roboticus (Chancellor) on Jun 27, 2014 at 17:49 UTC


    I'd suggest using a hash of hashes. The first hash key would be the name of the fruit, and the second would hold the + or -:

    my $key = 'cherry'; print "$key is positive!\n" if exists $strands{$key}{'+'}; print "$key is negative!\n" if exists $strands{$key}{'-'};


    When your only tool is a hammer, all problems look like your thumb.

Re: Unique key identifer?
by Laurent_R (Abbot) on Jun 27, 2014 at 21:17 UTC
    I don't really see the need or usefulness of the first file and array. Personally, on this specific case, I would use two hashes, one for the "+" values and one for the "-" values, because I do not think that a two-level data structure brings very much for this. This is my proposal:
    use strict; use warnings; my (%plus, %minus); while (<DATA>) { my ($fruit, $sign) = split; if ($sign eq '+') { $plus{$fruit} = 1; } else { $minus{$fruit} = 1; } } print "Positives are : ", (map "$_, ", keys %plus), "\n"; print "Negatives are : ", (map "$_, ", keys %minus), "\n"; __DATA__ apple + cherry - cherry + peach + banana -
    This yields the following output:
    $ perl Positives are : peach, cherry, apple, Negatives are : banana, cherry,
    As you can see, real code is about 12 lines or so.
      had the same idea, but then I realized it's not much different from a HoH after writing

      my %strands = ( '+' => \%plus, '-' => \%minus );

      as a side note, I'd prefer

      print "Positives are : ", join (', ', keys %plus), "\n";

      instead of map :)

      Cheers Rolf

      (addicted to the Perl Programming Language)

        I agree with you and thank you, LanX, I am really not against using a HoH. But there are some cases where a HoH is really the natural data structure, and others where it is debatable. In this specific case, I would think that a HoH does not bring any algorithmic advantage (that's what I tried to show), so that using two hashes is simpler for the beginner. But I am perfectly happy with a HoH.

        On your second point, well, yes, maybe, the only aim was just to print the output to show the results. The map function is the first one that came to my mind to format the output, using join is also a good possibility (perhaps a bit clearer to the beginner). But this is really just a result formatting issue. In brief, as we all know, TIMOWTDI.

      Thank you for your response. The 2 file structure is merely to mimic what I am trying to do for a more complicated program. I have to refer to another file which has for a particular "fruit", a + or -. From the information held in that file I then act on the data in the other file.

      My files are 44,000 lines long and created from some hefty scripting way out of my control, so needs to be kept in this structure.

      Will give this a go, thank you.

        Yeah, I also thought that your problem was probably not about apples, cherries and bananas. The reason I removed the opening and reading of the first file is that it was not useful for the problem you described, since all needed information was in the second file. I hope my suggested code still helps you, and I am sure many monks, including myself, will be glad to help you if you provide a scenario closer to your actual problem.
Re: Unique key identifer?
by Bodger (Novice) on Jun 28, 2014 at 15:12 UTC

    I have faced similar problems before.

    I take the key not as cherry but as
    cherry+ and cherry-
    simple example
    my %strands;
    # you could do this to the strand line
    $key = 'cherry    +';
    $key =~ s/ //g; # to remove spaces
    $strands{'cherry+'} = 1;
    then when you read cherry in, and you want cherry+
    if (exists $strands{'cherry+'})
        do_something ();
Re: Unique key identifer?
by 1s44c (Scribe) on Jun 28, 2014 at 17:26 UTC

    Maybe I'm misreading this and I'm not saying this is the best way to do it, but:

    push @{$strands{$key}}, $value;

    Looks like it should be:

    $strands{$key} .= $value;

    i.e. A hash value may contain both a '-' and a '+'.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1091498]
Approved by Jim
Front-paged by davies
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (3)
As of 2017-02-20 02:49 GMT
Find Nodes?
    Voting Booth?
    Before electricity was invented, what was the Electric Eel called?

    Results (293 votes). Check out past polls.