[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

add rankings to array?

soprano

1/6/2008 5:30:00 PM

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?

5 Answers

Carlos J. Hernandez

1/6/2008 5:57:00 PM

0

# soprano:
# How about just
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" <spicyjalapeno@gmail.com>
said:
> Is it possible to add rankings to an array (allowing ties):....

soprano

1/6/2008 6:11:00 PM

0

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).

Robert Klemme

1/6/2008 6:13:00 PM

0

On 06.01.2008 18:30, soprano wrote:
> 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?

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

soprano

1/6/2008 6:44:00 PM

0

Great, thanks!

On Jan 6, 11:15=A0am, Robert Klemme <shortcut...@googlemail.com> wrote:
> Preparation:
>
> data =3D [
> =A0 =A0{ :name =3D> "A", :points =3D> 30 },
> =A0 =A0{ :name =3D> "B", :points =3D> 20 },
> =A0 =A0{ :name =3D> "C", :points =3D> 10 },
> =A0 =A0{ :name =3D> "D", :points =3D> 20 }
> ]
>
> Here's one way:
>
> sorted =3D data.sort_by {|x| -x[:points]}
> ranked =3D sorted.inject([0,1,nil,[]]) do |(rk, cn, lst, arr), x|
> =A0 =A0tmp_lst =3D x[:points]
>
> =A0 =A0if tmp_lst =3D=3D lst
> =A0 =A0 =A0cn +=3D 1
> =A0 =A0else
> =A0 =A0 =A0rk +=3D cn
> =A0 =A0 =A0cn =A0=3D 1
> =A0 =A0end
>
> =A0 =A0[rk, cn, tmp_lst, arr << [rk, x]]
> end.last
>
> And here's another:
>
> hashed =3D data.inject(Hash.new {|h,k| h[k] =3D []}) do |ha, x|
> =A0 =A0ha[x[:points]] << x
> =A0 =A0ha
> end
> sorted =3D hashed.sort_by {|k,v| -k}
> ranked =3D sorted.inject([]) do |arr, (k,v)|
> =A0 =A0rk =3D arr.size + 1
> =A0 =A0v.each {|x, idx| arr << [rk, x]}
> =A0 =A0arr
> end
>
> Have fun!

Ken Bloom

1/6/2008 7:07:00 PM

0

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



--
Ken (Chanoch) Bloom. PhD candidate. Linguistic Cognition Laboratory.
Department of Computer Science. Illinois Institute of Technology.
http://www.iit.edu...