Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?

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 (Canon) 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
[oiskuu]: Ahem. Speaking of toxic injections.. Is there a simple way to inject into package a sub{} so that it captures a $variable that is declared package my?
[Corion]: oiskuu: No, which is why I hate package-scope lexicals
[marto]: yikes
[Corion]: Variables declared in a package should always be globals so that you can get at them from the outside
[oiskuu]: source filter to s/my/our/g :p
[robby_dobby]: oiskuu: Damn, you're evil.
[robby_dobby]: I was actually thinking of a source filter, you went ahead and voiced it!
[LanX]: not sure if I understand you but I think yes
[oiskuu]: Padwalker?
[LanX]: at least with PadWalker you can inspect the closure of a sub

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (13)
As of 2017-12-15 19:41 GMT
Find Nodes?
    Voting Booth?
    What programming language do you hate the most?

    Results (442 votes). Check out past polls.