Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > [Nuby] Sorting a Hash and keepint it as a Hash?

Reply
Thread Tools

[Nuby] Sorting a Hash and keepint it as a Hash?

 
 
Williams, Chris
Guest
Posts: n/a
 
      12-13-2004
------_=_NextPart_001_01C4E14F.4AE3BE3B
Content-Type: text/plain;
charset="us-ascii"
Content-Transfer-Encoding: quoted-printable

Another nuby question:

I have a Hash of objects which I want to sort by the values. Afterwards
I want to pull out the keys as one array and the values as another. So I
have code like so:

# sort by frequency ascending
@fault_sums =3D @fault_sums.sort {|a,b| a[1] <=3D> b[1]}
# Only keep top N
@fault_sums.slice!(0...-@number) if @number <=3D @fault_sums.size=20
=20
fields =3D @fault_sums.keys
data =3D @fault_sums.values

But when I get to calling keys and values on the Hash I realized, sort
actually returns back a 2D array and those methods aren't defined on an
Array. Is there a way to make the 2D Array returned by the sort back
into a Hash?

Thanks,
Chris Williams

------_=_NextPart_001_01C4E14F.4AE3BE3B--


 
Reply With Quote
 
 
 
 
Logan Capaldo
Guest
Posts: n/a
 
      12-13-2004
On Tue, 14 Dec 2004 05:07:03 +0900, Williams, Chris
<> wrote:
> Another nuby question:
>
> I have a Hash of objects which I want to sort by the values. Afterwards
> I want to pull out the keys as one array and the values as another. So I
> have code like so:
>
> # sort by frequency ascending
> @fault_sums = @fault_sums.sort {|a,b| a[1] <=> b[1]}
> # Only keep top N
> @fault_sums.slice!(0...-@number) if @number <= @fault_sums.size
>
> fields = @fault_sums.keys
> data = @fault_sums.values
>
> But when I get to calling keys and values on the Hash I realized, sort
> actually returns back a 2D array and those methods aren't defined on an
> Array. Is there a way to make the 2D Array returned by the sort back
> into a Hash?
>
> Thanks,
> Chris Williams
>
>

Well you could but you'd be back at square one since a hash is
unordered. An alternate method is to sort the keys by the values, ie

keys_ordered = some_hash.keys.sort { |a, b| some_hash[a] <=> some_hash[b] }

keys_ordered.each { |k|
# do something with some_hash[k]
}

Of course you'll have to change it to fit exactly what you need.


 
Reply With Quote
 
 
 
 
Robert Klemme
Guest
Posts: n/a
 
      12-13-2004
>
> "Williams, Chris" <> schrieb im Newsbeitrag
> news:A0AC2703C633EB48B5DFEF66D6EBF7120E49DD@wcxlms 02.wcrt.xeroxlabs.com...
> Another nuby question:
>
> I have a Hash of objects which I want to sort by the values. Afterwards
> I want to pull out the keys as one array and the values as another. So I
> have code like so:


You want sort with a block:

>> h={1=>"a",2=>"b"}

=> {1=>"a", 2=>"b"}
>> h.sort {|(k1,v1),(k2,v2)| v1 <=> v2}

=> [[1, "a"], [2, "b"]]

If you use inject you can get your two arrays in one go:

>> h.sort {|(k1,v1),(k2,v2)| v1 <=> v2}.inject([[],[]]) {|(ks,vs),(k,v)| ks
>> << k; vs << v; [ks,vs]}

=> [[1, 2], ["a", "b"]]
>> keys, values = h.sort {|(k1,v1),(k2,v2)| v1 <=> v2}.inject([[],[]])
>> {|(ks,vs),(k,v)| ks << k; vs << v; [ks,vs]}

=> [[1, 2], ["a", "b"]]
>> keys

=> [1, 2]
>> values

=> ["a", "b"]

> # sort by frequency ascending
> @fault_sums = @fault_sums.sort {|a,b| a[1] <=> b[1]}
> # Only keep top N
> @fault_sums.slice!(0...-@number) if @number <= @fault_sums.size
>
> fields = @fault_sums.keys
> data = @fault_sums.values
>
> But when I get to calling keys and values on the Hash I realized, sort
> actually returns back a 2D array and those methods aren't defined on an
> Array. Is there a way to make the 2D Array returned by the sort back
> into a Hash?


This won't help as the hash you get then is unsorted again. If you need a
copy, Hash#dup or Marshal.load(Marshal.dump(hash)) is a better choice.

Kind regards

robert

 
Reply With Quote
 
Florian Gross
Guest
Posts: n/a
 
      12-13-2004
Williams, Chris wrote:

> I have a Hash of objects which I want to sort by the values. Afterwards
> I want to pull out the keys as one array and the values as another. So I
> have code like so:
>
> # sort by frequency ascending
> @fault_sums = @fault_sums.sort {|a,b| a[1] <=> b[1]}
> # Only keep top N
> @fault_sums.slice!(0...-@number) if @number <= @fault_sums.size
>
> fields = @fault_sums.keys
> data = @fault_sums.values
>
> But when I get to calling keys and values on the Hash I realized, sort
> actually returns back a 2D array and those methods aren't defined on an
> Array. Is there a way to make the 2D Array returned by the sort back
> into a Hash?


There's no sorted Hashs in Standard Ruby so you will get a sorted Array
of pairs.

However you can use a nifty trick to get the keys and values out of that:

[['key1', 'value1'], ['key2', 'value2']].transpose
# => [['key1', 'key2'], ['value1', 'value2']]

So this will solve your problem:

top_pairs = @faults_sum.sort_by { |key, value| -value }.first(@number)
fields, data = *top_pairs.transpose

Note that I chose to sort descending and to keep the first (high sum)
entries instead of sorting ascending and to keep the lowest (high sum)
entries in reverse.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
hash of hash of hash of hash in c++ rp C++ 1 11-10-2011 04:45 PM
Hash and Array sorting - a bit confused Alpha Blue Ruby 2 09-02-2009 09:27 PM
Hash#select returns an array but Hash#reject returns a hash... Srijayanth Sridhar Ruby 19 07-02-2008 12:49 PM
fired event Sorting which wasn't handled - sorting and SelectedIndexChanged Jason ASP .Net Web Controls 0 10-04-2006 02:19 PM
Sorting a hash containing a hash of hashes IanW Perl Misc 3 12-14-2005 03:02 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57