How to sort this hash?

X

x1

Is it possible to sort the jobs hash below based on values such as
command, start_time and stop_time?

Ideally, sort_by would be dynamically provided and I would output the
jobs entries based on the value defined for sort_by.



--------------------------(basic_script.rb)------------------------
sort_by =3D "start_time" #<---- I'd like to use something like this to
define which job is listed first

jobs =3D {
=09=09"2231" =3D> {"command" =3D> "test_a.bash",
=09=09=09=09"start_time" =3D> "20051211",
=09=09=09=09"stop_time" =3D> "20051222"},
=09=09"1131" =3D> {"command" =3D> "test_b.bash",
=09=09=09=09"start_time" =3D> "20051011",
=09=09=09=09"stop_time" =3D> "20051122"},
=09=09"231" =3D> {"command" =3D> "test_c.bash",
=09=09=09=09"start_time" =3D> "20051215",
=09=09=09=09"stop_time" =3D> "20051227"}
=09}

jobs.each do |job, attributes|
puts "------------------"
=09puts attributes["command"]
=09puts attributes["start_time"]
=09puts attributes["stop_time"]
end
--------------------------(/basic_script.rb)------------------------

This is the default output:
./basic_script.rb
------------------
test_c.bash
20051215
20051227
------------------
test_b.bash
20051011
20051122
------------------
test_a.bash
20051211
20051222


Id like to have the dynamics of say, ordering these by attribute such
as start_time:

(I wish I could get this)
test_b.bash
20051011
20051122
------------------
test_a.bash
20051211
20051222
------------------
test_c.bash
20051215
20051227


Any suggestions?

thanks in advance.
 
F

Florian Groß

x1 said:
Is it possible to sort the jobs hash below based on values such as
command, start_time and stop_time?

Ideally, sort_by would be dynamically provided and I would output the
jobs entries based on the value defined for sort_by.

sort_by = "start_time" #<---- I'd like to use something like this to
define which job is listed first

jobs = {
"2231" => {"command" => "test_a.bash",
"start_time" => "20051211",
"stop_time" => "20051222"},
"1131" => {"command" => "test_b.bash",
"start_time" => "20051011",
"stop_time" => "20051122"},
"231" => {"command" => "test_c.bash",
"start_time" => "20051215",
"stop_time" => "20051227"}
}

sort_keys = ["start_time", "stop_time"]
jobs.sort_by do |job|
sort_keys.map do |key|
job[key]
end
end

Note that this will only work as long as all sort_keys are present in
every job.

You might want to check the documentation for Enumerable#sort_by, but
let me document the special thing in this case as well.

sort_by's block can return multiple values as an Array. In that case it
will first sort by the first value then by the second one and so on.
This is used in the above sample where every job is sorted by the fields
representing the sort_keys on that specific job.
 
S

Simon Kröger

x1 said:
Is it possible to sort the jobs hash below based on values such as
command, start_time and stop_time?

Ideally, sort_by would be dynamically provided and I would output the
jobs entries based on the value defined for sort_by.

This should do:

jobs.sort{|a,b|a[1][sort_by] <=> b[1][sort_by]}.each do |k, attributes|
puts "------------------"
puts attributes["command"]
puts attributes["start_time"]
puts attributes["stop_time"]
end

cheers

Simon
 
X

x1

Thank you for the reply.

I tried adding your suggestions but ended up with an error:
ruby array_test.rb
array_test.rb:19:in `[]': cannot convert String into Integer (TypeError)
=09from array_test.rb:19
=09from array_test.rb:18:in `map'
=09from array_test.rb:18
=09from array_test.rb:17:in `sort_by'
=09from array_test.rb:17:in `each'
=09from array_test.rb:17:in `sort_by'
=09from array_test.rb:17
Exit code: 1


The script is:

--------------------------------------

jobs =3D {
=09=09"2231" =3D> {"command" =3D> "test_a.bash",
=09=09=09=09"start_time" =3D> "20051211",
=09=09=09=09"stop_time" =3D> "20051222"},
=09=09"1131" =3D> {"command" =3D> "test_b.bash",
=09=09=09=09"start_time" =3D> "20051011",
=09=09=09=09"stop_time" =3D> "20051122"},
=09=09"231" =3D> {"command" =3D> "test_c.bash",
=09=09=09=09"start_time" =3D> "20051215",
=09=09=09=09"stop_time" =3D> "20051227"}
=09}

sort_keys =3D ["start_time", "stop_time"]
jobs.sort_by do |job|
=09sort_keys.map do |key|
=09=09job[key]
=09end
end

x1 said:
Is it possible to sort the jobs hash below based on values such as
command, start_time and stop_time?

Ideally, sort_by would be dynamically provided and I would output the
jobs entries based on the value defined for sort_by.

sort_by =3D "start_time" #<---- I'd like to use something like this to
define which job is listed first

jobs =3D {
"2231" =3D> {"command" =3D> "test_a.bash",
"start_time" =3D> "20051211",
"stop_time" =3D> "20051222"},
"1131" =3D> {"command" =3D> "test_b.bash",
"start_time" =3D> "20051011",
"stop_time" =3D> "20051122"},
"231" =3D> {"command" =3D> "test_c.bash",
"start_time" =3D> "20051215",
"stop_time" =3D> "20051227"}
}

sort_keys =3D ["start_time", "stop_time"]
jobs.sort_by do |job|
sort_keys.map do |key|
job[key]
end
end

Note that this will only work as long as all sort_keys are present in
every job.

You might want to check the documentation for Enumerable#sort_by, but
let me document the special thing in this case as well.

sort_by's block can return multiple values as an Array. In that case it
will first sort by the first value then by the second one and so on.
This is used in the above sample where every job is sorted by the fields
representing the sort_keys on that specific job.
 
X

x1

Simon!! That worked :-D *huge grin*

If you don't mind me asking, have you had to use this before? I
wouldnt consider myself a top notch developer but between the ruby
docs and google searches, I would have never figured this out...

Any tips out how you did? Just.. development experience? Thanks again!!

Thank you for the reply.

I tried adding your suggestions but ended up with an error:
ruby array_test.rb
array_test.rb:19:in `[]': cannot convert String into Integer (TypeError)
from array_test.rb:19
from array_test.rb:18:in `map'
from array_test.rb:18
from array_test.rb:17:in `sort_by'
from array_test.rb:17:in `each'
from array_test.rb:17:in `sort_by'
from array_test.rb:17
Exit code: 1


The script is:

--------------------------------------

jobs =3D {
"2231" =3D> {"command" =3D> "test_a.bash",
"start_time" =3D> "20051211",
"stop_time" =3D> "20051222"},
"1131" =3D> {"command" =3D> "test_b.bash",
"start_time" =3D> "20051011",
"stop_time" =3D> "20051122"},
"231" =3D> {"command" =3D> "test_c.bash",
"start_time" =3D> "20051215",
"stop_time" =3D> "20051227"}
}

sort_keys =3D ["start_time", "stop_time"]
jobs.sort_by do |job|
sort_keys.map do |key|
job[key]
end
end

x1 said:
Is it possible to sort the jobs hash below based on values such as
command, start_time and stop_time?

Ideally, sort_by would be dynamically provided and I would output the
jobs entries based on the value defined for sort_by.

sort_by =3D "start_time" #<---- I'd like to use something like this = to
define which job is listed first

jobs =3D {
"2231" =3D> {"command" =3D> "test_a.bash",
"start_time" =3D> "20051211",
"stop_time" =3D> "20051222"},
"1131" =3D> {"command" =3D> "test_b.bash",
"start_time" =3D> "20051011",
"stop_time" =3D> "20051122"},
"231" =3D> {"command" =3D> "test_c.bash",
"start_time" =3D> "20051215",
"stop_time" =3D> "20051227"}
}

sort_keys =3D ["start_time", "stop_time"]
jobs.sort_by do |job|
sort_keys.map do |key|
job[key]
end
end

Note that this will only work as long as all sort_keys are present in
every job.

You might want to check the documentation for Enumerable#sort_by, but
let me document the special thing in this case as well.

sort_by's block can return multiple values as an Array. In that case it
will first sort by the first value then by the second one and so on.
This is used in the above sample where every job is sorted by the field= s
representing the sort_keys on that specific job.
 
J

Jeff Cohen

Simon, would you be willing to explain the syntax you used here:
jobs.sort{|a,b|a[1][sort_by] <=> b[1][sort_by]}.each do |k, attributes|


I just can't quite understand the [sort_by] usage here...?

Thanks (and apologies for the newbieness :)

Jeff
 
F

Florian Groß

x1 said:
I tried adding your suggestions but ended up with an error:

Ah, I was assuming jobs to be an Array in error.

Please try this instead:

sort_keys = ["start_time", "stop_time"]
jobs.sort_by do |key, job|
sort_keys.map do |key|
job[key]
end
end
 
F

Florian Groß

Jeff said:
jobs.sort{|a,b|a[1][sort_by] <=> b[1][sort_by]}.each do |k, attributes|
I just can't quite understand the [sort_by] usage here...?

It looks up the value in the hash from a[1] (a[0] is "2231" / "1131" /
"231" for the sample data) that represents to the key identified by sort_by.

So if sort_by is "command" it will sort the jobs by the value
corresponding to their "command" key. Which is "test_a.bash" for job
"2231", "test_b.bash" for job "1131", "test_c.bash" for job "231" and so
on...
 
J

Jeff Cohen

So if sort_by is "command" it will sort the jobs by the value

Ah! I thought it was referring to something related to
Enumerable.sort_by.

Got it. Thanks.
 
A

Adam Akhtar

jobs.sort{|a,b|a[1][sort_by] <=> b[1][sort_by]}.each do |k, attributes|
puts "------------------"
puts attributes["command"]
puts attributes["start_time"]
puts attributes["stop_time"]
end


Im a newb but i wouldnt have thought a[1][sort_by] would have worked. I
tried accessing this hash in irb in the same way

a = {"job" = > {"wage" => 30, "time" => 60}}

a[1]["wage"] and got an error
NoMethodError: undefined method `[]' for nil:NilClass

why does it work???? Can you only access a hash like that within a sort
block?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,152
Members
46,698
Latest member
LydiaHalle

Latest Threads

Top