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

Hi Brethren,
I would like to remove the second pair of numbers and the comma from the following data and then split the remainder into a hash. All my attempts so far have resulted in the second pair of numbers and the line of text ending in the hash key. The original data is the result of a map and join function join "\n", map {"$_->[0]\t " . join ' ', @{$_->[1]}} @UnNum;
73 63, galileo measur us newton basi law motion 75 45, galileo experi bodi roll slope act same forc weight effect +make constantli speed up 70 50, show real effect forc chang speed bodi set move previous th +ought 75 50, meant bodi act forc keep move straight line same speed 65 45, idea first state explicitli newton principia mathematica pu +blish 1687 known newton first law 75 50, happen bodi forc act given newton second law
I am hoping to get the follow dat into the key / values
key value 73 galileo measur us newton 75 galileo experi bodi 70 show real effect forc
Any help will be much appreciated

Replies are listed 'Best First'.
Re: Split results of Map function
by jdporter (Paladin) on Apr 08, 2006 at 13:22 UTC

    I'm inferring that by "second pair of numbers" you mean "the second number in each pair of numbers".

    while (<DATA>) # or wherever those lines come from { chomp; my( $num, $str ) = split ' ', $_, 2; $str =~ s/^\d+,\s*//; $hash{$num} = $str; }
    or
    while (<DATA>) # or wherever those lines come from { /^(\d+)\s+\d+,\s*(.*)/ and $hash{$1} = $2; }
    We're building the house of the future together.
Re: Split results of Map function
by McDarren (Abbot) on Apr 08, 2006 at 13:30 UTC
    Are you sure you really want a hash?

    If you use the first two numbers digits as keys to a hash, then you will wind up with duplicate keys, and some of your data will be lost.

    Of course this may be what you want. But if not, perhaps what you really want is a LoL

    Update 1: the following code shows you the difference between putting your data into a hash, or a LoL (List of Lists)..

    Update 2: actually, that's not a LoL at all - it's just a straight list. If we change the @LOL assignment to read:

    push @LoL, [$key, $value];
    then we get a LoL :)
    I confused myself because I initially thought you wanted to separate all the words on each line. But anyway, I'm sure you get the idea :)
    #!/usr/bin/perl -wl use strict; use Data::Dumper::Simple; my %hash; my @LoL; while (<DATA>) { chomp; my ($key, undef, $value) = split /\s+/, $_, 3; $hash{$key} = $value; push @LoL, $key, $value; } print Dumper(%hash); print Dumper(@LoL); __DATA__ 73 63, galileo measur us newton basi law motion 75 45, galileo experi bodi roll slope act same forc weight effect +make constantli speed up 70 50, show real effect forc chang speed bodi set move previous th +ought 75 50, meant bodi act forc keep move straight line same speed 65 45, idea first state explicitli newton principia mathematica pu +blish 1687 known newton first law 75 50, happen bodi forc act given newton second law
    Output:
    %hash = ( '70' => 'show real effect forc chang speed bodi set move pre +vious thought', '75' => 'happen bodi forc act given newton second law', '73' => 'galileo measur us newton basi law motion', '65' => 'idea first state explicitli newton principia mathem +atica publish 1687 known newton first law' ); @LoL = ( '73', 'galileo measur us newton basi law motion', '75', 'galileo experi bodi roll slope act same forc weight effect m +ake constantli speed up', '70', 'show real effect forc chang speed bodi set move previous tho +ught', '75', 'meant bodi act forc keep move straight line same speed', '65', 'idea first state explicitli newton principia mathematica pub +lish 1687 known newton first law', '75', 'happen bodi forc act given newton second law' );

    Cheers,
    Darren :)

      Hi All
      Thanks all for the input.
      I had not appreciated that there could be multiple keys with the same value.
      I need to be able to keep all duplicate numbers in the hash. Is there a way of switching the data between key / value as the text is actually unique and would be ideal as the key.
      RegardGavin
        That's simple: just say $hash{$v} = $k instead of $hash{$k} = $v :)
Re: Split results of Map function
by rhesa (Vicar) on Apr 08, 2006 at 13:25 UTC
    split on /\s+\d+,\s+/:
    while(<DATA>) { chomp; my ($k, $v) = split / \s+ \d+ , \s+ /x; print "key: $k ... value: $v$/"; # or stuff it in a hash: $hash{$k} = $v; } __DATA__ 73 63, galileo measur us newton basi law motion 75 45, galileo experi bodi roll slope act same forc weight effect +make constantli speed up 70 50, show real effect forc chang speed bodi set move previous th +ought 75 50, meant bodi act forc keep move straight line same speed 65 45, idea first state explicitli newton principia mathematica pu +blish 1687 known newton first law 75 50, happen bodi forc act given newton second law
Re: Split results of Map function
by graff (Chancellor) on Apr 08, 2006 at 16:07 UTC
    As pointed out above, your sample data and your description of the task will lead to the same numeric string being treated as a hash key for several distinct values.

    Based on what you describe as the desired output, it looks like you want to keep just the first value assoicated with a given key, and ignore later values. (But you didn't actually say this, so I'm just guessing.) If that is the case, you would want to alter the code in one of the earlier replies so that you check for the existence of a hash key before you assign a value to it. Using thesa's solution, for instance:

    my %hash = (); while(<DATA>) { chomp; my ($k, $v) = split / \s+ \d+ , \s+ /x; $hash{$k} = $v unless exists $hash{$k}; }
    This will make sure that once a value is assigned to a given hash key, no other value will be assigned to that key (assuming this is what you want).