On 03/08/2011 19:12, Marc wrote: > > I'm trying to sort a shopping cart basket on the item numbers. The > basket is stored in a hash. There is a hashref called > %{$main::global->{cart}} that Data::Dumper prints out like so: > > $VAR1 = { > '1' => '1 1 SL-8206 > 73.15 Label 8.25" x 6" 0.8 > 73.15 ', > '3' => '3 1 WR-9253 > 13.98 Label - 3" x 9" 0.5 > 13.98 ', > '2' => '2 1 APT-46V > 96.43 4"x6" Label, hook 1.8 > 96.43 ' > }; > > I would like to grab the item numbers, i.e. SL-8206, to sort the cart > on. Could someone point me to something to read up on this? What is > the above actually? It looks to me like a hash of hashes of > arrays(?).
Hi Marc Take a look at perldoc perlreftut and perldoc perlref to read up on nested data structures. But what you have here is a simple hash - there is no nesting at all unless you count {cart} which is an element of the hash referenced by $global. The hash %{$global->{cart}} has three elements, with keys '1', '3' and '2' and values equal to the long string the other side of =>. There is nothing special about those values - they are simple strings that happen to have several prices of information in them, separated by whitespace. > I thought that converting it into an array would help, like so: > > my $n = keys($main::global->{cart}); I think this can't be what you wrote - it wouldn't compile. You probably want my $n = keys %{$global->{cart}}; > my @cart_lineitems = @{$main::global->{cart}}{0 .. $n}; That is one way of doing things, but I am surprised you happened upon it without knowing more about Perl. You have written a hash slice that indexes the array using integers. But hash keys are strings, and it is fortunate that Perl converts numbers to strings appropriately for this hash. (For instance, the element $global->{cart}{'1'} is different and separate from the element $global->{cart}{'01'}.) I would write my @cart_lineitems; foreach my $i (keys %{global->{cart}}) { $cart_lineitems[$i] = $global->{cart}{$i}; } although the functionality is equivalent and some would say this way involves unnecessary code. > but dumping the output: > > print {$tracelog_fh} Dumper($cart_lineitems[0]); > print {$tracelog_fh} Dumper($cart_lineitems[1]); > print {$tracelog_fh} Dumper($cart_lineitems[2]); > print {$tracelog_fh} Dumper($cart_lineitems[3]); > > gives me this: > > $VAR1 = ''; > $VAR1 = '1 1 SL-8206 73.15 > Label 8.25" x 6" 0.8 73.15 > '; > $VAR1 = '2 1 APT-46V 13.98 > Label - 3" x 9" 1.8 13.98 > '; > $VAR1 = '3 1 WR-9253 96.43 > 4"x6" Label, hook 0.5 96.43 > '; > > Why the first one is empty is beyond me, but that's another story. The first element is empty because you have assigned values at indices [1], [2] and [3]. The first element is at [0] and you have left it untouched. > I then tried to grab just the item numbers using both: > > print {$tracelog_fh} Dumper($cart_lineitems[1][2]); > > and > > print {$tracelog_fh} Dumper($main::global->{cart}->{1}->{2}); > > but they produce these errors: > > Can't use string ("1 1 SL-8206 > 73.15 Label "...) as an ARRAY ref while > "strict refs" in use > > Can't use string ("1 1 SL-8206 > 73.15 Label "...) as an HASH ref while > "strict refs" in use Because the values of the array elements are simple strings, as I explained above, you must find a way of splitting them into individual fields. The simple way would be to use the 'split' operator to divide the line at whitespace, but the presence of spaces in the description field spoils that approach. Without knowing more about your data, I can suggest that you split on sequences of two or more whitespace characters, like this my @cart_lineitems; foreach my $i (keys %{$global->{cart}}) { $cart_lineitems[$i] = [ split /\s{2,}/, $global->{cart}{$i} ]; } which dumps like this @cart_lineitems = ( undef, [ '1 1 SL-8206', '73.15', 'Label 8.25" x 6"', '0.8 73.15 ' ], [ '2 1 APT-46V', '96.43', '4"x6" Label, hook', '1.8 96.43 ' ], [ '3 1 WR-9253', '13.98', 'Label - 3" x 9"', '0.5 13.98 ' ] ); Which is reasonable, but you still have trailing spaces at the end of the final field, which may or may not be a problem. > Anyway, maybe I'm going about this the wrong way. I know enough just > to be dangerous at this point. The bottom line is, how would I go > about grabbing the item numbers from the original hashref so that I > can sort the cart on them? I'm over my head with this one, so any > pointers would be extremely helpful. I'm reading about references in > the "Beginning Perl" book, but so far the light hasn't come on. Grabbing just the item numbers (the third field) doesn't involve any column that can contain embedded spaces, so you can just sort on the value of ( split ' ', $lineitem )[2] as shown in the program below. Depending on what else you want to do with your data, it may well be better to store it in a different format, but I hope this serves to help you with your initial problem. Cheers, Rob use strict; use warnings; use Data::Dumper; our $global; $global->{cart} = { '1' => '1 1 SL-8206 73.15 Label 8.25" x 6" 0.8 73.15 ', '3' => '3 1 WR-9253 13.98 Label - 3" x 9" 0.5 13.98 ', '2' => '2 1 APT-46V 96.43 4"x6" Label, hook 1.8 96.43 ', }; my @cart_lineitems = sort { ( split ' ', $a)[2] cmp ( split ' ', $b)[2]; } values %{$global->{cart}}; print Data::Dumper->Dump([\@cart_lineitems], ['*cart_lineitems']); **OUTPUT** @cart_lineitems = ( '2 1 APT-46V 96.43 4"x6" Label, hook 1.8 96.43 ', '3 1 WR-9253 13.98 Label - 3" x 9" 0.5 13.98 ', '1 1 SL-8206 73.15 Label 8.25" x 6" 0.8 73.15 ' ); -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/