Is it possible to add rankings to an array (allowing ties):

Example (rate on points field) - convert

[
{ :name => “A”, :points => 30 },
{ :name => “B”, :points => 20 },
{ :name => “C”, :points => 10 },
{ :name => “D”, :points => 20 }
]

to

[
[1, { :name => “A”, :points => 30 }],
[2, { :name => “B”, :points => 20 }],
[2, { :name => “D”, :points => 20 }],
[4, { :name => “C”, :points => 10 }]
]

How to do this in Ruby?

# soprano:

listA = [[“A”,30], [“B”,20], [“C”,10], [“D”,20]]

# Or

listH = { “A”=>30, “B”=>20, “C”=>10, “D”=>20 }

# Then sort the list

listSA = listA.sort{|a,b| ret = b[1]<=>a[1]; (ret==0)? a[0]<=>b[0]: ret}

# Works also with listH

listSH = listH.sort{|a,b| ret = b[1]<=>a[1]; (ret==0)? a[0]<=>b[0]: ret}

On Mon, 7 Jan 2008 02:30:13 +0900, “soprano” [email protected]
said:

Yes, I see how to sort an array, but that will produce (unless I am
mistaken):

[
[1, { :name => “A”, :points => 30 }],
[2, { :name => “B”, :points => 20 }],
[3, { :name => “D”, :points => 20 }],
[4, { :name => “C”, :points => 10 }]
]

and I want to account for ties (in points).

On 06.01.2008 18:30, soprano wrote:

to

[
[1, { :name => “A”, :points => 30 }],
[2, { :name => “B”, :points => 20 }],
[2, { :name => “D”, :points => 20 }],
[4, { :name => “C”, :points => 10 }]
]

How to do this in Ruby?

Preparation:

data = [
{ :name => “A”, :points => 30 },
{ :name => “B”, :points => 20 },
{ :name => “C”, :points => 10 },
{ :name => “D”, :points => 20 }
]

Here’s one way:

sorted = data.sort_by {|x| -x[:points]}
ranked = sorted.inject([0,1,nil,[]]) do |(rk, cn, lst, arr), x|
tmp_lst = x[:points]

if tmp_lst == lst
cn += 1
else
rk += cn
cn = 1
end

[rk, cn, tmp_lst, arr << [rk, x]]
end.last

And here’s another:

hashed = data.inject(Hash.new {|h,k| h[k] = []}) do |ha, x|
ha[x[:points]] << x
ha
end
sorted = hashed.sort_by {|k,v| -k}
ranked = sorted.inject([]) do |arr, (k,v)|
rk = arr.size + 1
v.each {|x, idx| arr << [rk, x]}
arr
end

Have fun!

Kind regards

robert

On Sun, 06 Jan 2008 13:11:02 -0500, soprano wrote:

Yes, I see how to sort an array, but that will produce (unless I am
mistaken):

[
[1, { :name => “A”, :points => 30 }], [2, { :name => “B”, :points =>
20 }], [3, { :name => “D”, :points => 20 }], [4, { :name => “C”,
:points => 10 }]
]

and I want to account for ties (in points).

Assuming you have the array above after sorting, make a pass across it
as
follows:

a.times do |n|
a[n][0]=a[n-1][0] if a[n][1][:points]==a[n-1][1][:points]
end

Great, thanks!