Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

sort hash by value

by glenn (Scribe)
on Mar 24, 2014 at 12:55 UTC ( #1079517=perlquestion: print w/replies, xml ) Need Help??

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

I have this hash however I cannot for the life of me figure out how to apply sort to it. I have posted part of the hash but enough to make my point. I need to sort by the forth array value ie: $licensehash{CI}{CI_CTAG}[3]; Any ideas out there? Bonus: one line foreach loop.
our %licensehash = ( CI => { CI_CTAG => ['','',"", "Customer Name", 1, '[^0-9a-zA-Z\-]', [@ +new_license_versions]], CI_CID => ['','',"", "Chassis Serial", 1, '[^0-9a-zA-Z]', [@ne +w_license_versions]], CI_UID1 => ['','',"", "MAC 1/UUID", 0, '[^0-9a-zA-Z:-]', [$iTX +_2_7_VERSION, $iTX_SBB_VERSION_val]], CI_UID2 => ['','',"", "MAC 2", 0, '[^0-9a-zA-Z:-]', [$iTX_2_7_ +VERSION]], CI_SER => ['','',"", "Lenovo Serial", 0, '[^0-9a-zA-Z]', [$iTX +_Lenovo_VERSION_val]], CI_UUID => ['','',"", "Lenovo UUID", 0, '[^0-9a-zA-Z]', [$iTX_ +Lenovo_VERSION_val]], CI_E => ['','',"0", "Epoc", 0, '[^0-9]', [@new_license_version +s]], #0 unlicensed, 1 first license }, COM => { COM_PV => ['','',$iTX_SBB_VERSION_val, "iTX Version", 1, '[^0- +9.]', [@new_license_versions]], COM_MV => ['','',$VERSION, "LMU Version", 0, '[^0-9.]', [@new_ +license_versions]], COM_KT => ['','',"MASTER", "Key Type", 0, 'MASTER', [@new_lice +nse_versions]], COM_CD => ['','',sub{sprintf '%04d-%02d-%02d', $_[5]+1900, $_[ +4]+1, $_[3]}->(localtime), "Creation Date", 0, '[^0-9\-]', [@new_lice +nse_versions]], COM_USER => ['','',sub{qx"echo %username%"}, "Creation User", +0, '[^0-9a-zA-Z\-]', [@new_license_versions]], }, ISCSI => { ISCSI_T => ['','',"-1", "iSCSI", 1, "-1,89478485", [@new_licen +se_versions]], }, NAS => { NAS_T => ['','',"0", "NAS", 1, "-1,89478485", [$iTX_Lenovo_VER +SION_val, $iTX_2_7_VERSION]], }, RPL => { RPL_T => ['','',"-1", "Sync Replication", 1, "-1,89478485", [@ +new_license_versions]], }, ); #Help/fix me please foreach my $tag (keys %licensehash) { foreach my $type (keys %{$licensehash{$tag}}) { print "$licensehash{$tag}{$type}[3]: $licensehash{$tag}{$type} +[0]"; } }

Replies are listed 'Best First'.
Re: sort hash by value (sort array)
by Anonymous Monk on Mar 24, 2014 at 13:01 UTC
      That would be easier except this is tied into a GUI and user values are going into array 0, old values are in array 1. I think you may have given me an answer anyhow though; flaten tag, type, and string into a 2d array then sort then use that output to order the hash output...
      #head of code my @array; foreach my $tag (keys %licensehash) { foreach my $type (keys %{$licensehash{$tag}}) { push(@array, [$tag,$type,$licensehash{$tag}{$type}[3]]); } } @array = sort {$a->[2] cmp $b->[2]} @array; #body of program (used more than once) foreach my $order (@array) { print "$licensehash{@$order[0]}{@$order[1]}[3]"; }
Re: sort hash by value
by GrandFather (Saint) on Mar 25, 2014 at 01:18 UTC

    You can nest maps in much the same way you can nest for loops. It's not clear that there is a win doing that here, but consider:

    my @items = map {$licensehash{$_->[0]}{$_->[1]}} sort {$a->[2] cmp $b- +>[2]} map { my $top = $_; map {[$top, $_, $licensehash{$top}{$_}[3]]} keys %{$licensehash{$_ +}} } keys %licensehash; print "$_->[3]: $_->[0]\n" for @items;

    Prints:

    Chassis Serial: Creation Date: Creation User: Customer Name: Epoc: Key Type: LMU Version: Lenovo Serial: Lenovo UUID: MAC 1/UUID: MAC 2: NAS: Sync Replication: iSCSI: iTX Version:

    Note that @items contains the sorted values rather than the keys which cleans up the print statement somewhat. The map just to the right of the @items assignment does the lookup.

    If the code changes take longer than the time saved, it's fast enough already.
Re: sort hash by value
by kcott (Archbishop) on Mar 25, 2014 at 08:54 UTC

    G'day glenn,

    Perhaps something like this. It carries the $tag and $type keys through the sorting process; this allows the %licensehash data to be recreated in the sort order you want. If this isn't what you want, please show expected output.

    #!/usr/bin/env perl -l use strict; use warnings; no strict 'vars'; our %licensehash = ( CI => { CI_CTAG => ['','',"", "Customer Name", 1, '[^0-9a-zA-Z\-]', [@ +new_license_versions]], CI_CID => ['','',"", "Chassis Serial", 1, '[^0-9a-zA-Z]', [@ne +w_license_versions]], CI_UID1 => ['','',"", "MAC 1/UUID", 0, '[^0-9a-zA-Z:-]', [$iTX +_2_7_VERSION, $iTX_SBB_VERSION_val]], CI_UID2 => ['','',"", "MAC 2", 0, '[^0-9a-zA-Z:-]', [$iTX_2_7_ +VERSION]], CI_SER => ['','',"", "Lenovo Serial", 0, '[^0-9a-zA-Z]', [$iTX +_Lenovo_VERSION_val]], CI_UUID => ['','',"", "Lenovo UUID", 0, '[^0-9a-zA-Z]', [$iTX_ +Lenovo_VERSION_val]], CI_E => ['','',"0", "Epoc", 0, '[^0-9]', [@new_license_version +s]], #0 unlicensed, 1 first license }, COM => { COM_PV => ['','',$iTX_SBB_VERSION_val, "iTX Version", 1, '[^0- +9.]', [@new_license_versions]], COM_MV => ['','',$VERSION, "LMU Version", 0, '[^0-9.]', [@new_ +license_versions]], COM_KT => ['','',"MASTER", "Key Type", 0, 'MASTER', [@new_lice +nse_versions]], COM_CD => ['','',sub{sprintf '%04d-%02d-%02d', $_[5]+1900, $_[ +4]+1, $_[3]}->(localtime), "Creation Date", 0, '[^0-9\-]', [@new_lice +nse_versions]], COM_USER => ['','',sub{qx"echo %username%"}, "Creation User", +0, '[^0-9a-zA-Z\-]', [@new_license_versions]], }, ISCSI => { ISCSI_T => ['','',"-1", "iSCSI", 1, "-1,89478485", [@new_licen +se_versions]], }, NAS => { NAS_T => ['','',"0", "NAS", 1, "-1,89478485", [$iTX_Lenovo_VER +SION_val, $iTX_2_7_VERSION]], }, RPL => { RPL_T => ['','',"-1", "Sync Replication", 1, "-1,89478485", [@ +new_license_versions]], }, ); use strict 'vars'; my @to_sort; foreach my $tag (keys %licensehash) { foreach my $type (keys %{$licensehash{$tag}}) { push @to_sort, [$tag, $type, $licensehash{$tag}{$type}[3]]; } } my @sorted = sort { $a->[2] cmp $b->[2] } @to_sort; use Data::Dump; for (@sorted) { print "Sort value: $_->[2]; Tag key: $_->[0]; Type key: $_->[1]"; dd $licensehash{$_->[0]}{$_->[1]}; }

    Output:

    Sort value: Chassis Serial; Tag key: CI; Type key: CI_CID ["", "", "", "Chassis Serial", 1, "[^0-9a-zA-Z]", []] Sort value: Creation Date; Tag key: COM; Type key: COM_CD ["", "", "2014-03-25", "Creation Date", 0, "[^0-9\\-]", []] Sort value: Creation User; Tag key: COM; Type key: COM_USER ["", "", sub { ... }, "Creation User", 0, "[^0-9a-zA-Z\\-]", []] Sort value: Customer Name; Tag key: CI; Type key: CI_CTAG ["", "", "", "Customer Name", 1, "[^0-9a-zA-Z\\-]", []] Sort value: Epoc; Tag key: CI; Type key: CI_E ["", "", 0, "Epoc", 0, "[^0-9]", []] Sort value: Key Type; Tag key: COM; Type key: COM_KT ["", "", "MASTER", "Key Type", 0, "MASTER", []] Sort value: LMU Version; Tag key: COM; Type key: COM_MV ["", "", undef, "LMU Version", 0, "[^0-9.]", []] Sort value: Lenovo Serial; Tag key: CI; Type key: CI_SER ["", "", "", "Lenovo Serial", 0, "[^0-9a-zA-Z]", [undef]] Sort value: Lenovo UUID; Tag key: CI; Type key: CI_UUID ["", "", "", "Lenovo UUID", 0, "[^0-9a-zA-Z]", [undef]] Sort value: MAC 1/UUID; Tag key: CI; Type key: CI_UID1 ["", "", "", "MAC 1/UUID", 0, "[^0-9a-zA-Z:-]", [undef, undef]] Sort value: MAC 2; Tag key: CI; Type key: CI_UID2 ["", "", "", "MAC 2", 0, "[^0-9a-zA-Z:-]", [undef]] Sort value: NAS; Tag key: NAS; Type key: NAS_T ["", "", 0, "NAS", 1, "-1,89478485", [undef, undef]] Sort value: Sync Replication; Tag key: RPL; Type key: RPL_T ["", "", -1, "Sync Replication", 1, "-1,89478485", []] Sort value: iSCSI; Tag key: ISCSI; Type key: ISCSI_T ["", "", -1, "iSCSI", 1, "-1,89478485", []] Sort value: iTX Version; Tag key: COM; Type key: COM_PV ["", "", undef, "iTX Version", 1, "[^0-9.]", []]

    -- Ken

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1079517]
Approved by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (6)
As of 2023-12-06 17:40 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    What's your preferred 'use VERSION' for new CPAN modules in 2023?











    Results (31 votes). Check out past polls.

    Notices?