# Add rankings to array?

**URL:** <https://www.ruby-forum.com/t/add-rankings-to-array/125176>\
**Category:** Ruby\
**Created:** [January 6, 2008, 6:31pm UTC](https://www.ruby-forum.com/t/add-rankings-to-array/125176 "2008-01-06T18:31:06Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![soprano](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b3f665/32.png) [@soprano](https://www.ruby-forum.com/u/soprano)\
**Post date:** [January 6, 2008, 6:31pm UTC](https://www.ruby-forum.com/t/add-rankings-to-array/125176/1 "2008-01-06T18:31:06Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![soprano](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b3f665/32.png) [@soprano](https://www.ruby-forum.com/u/soprano)\
**Post date:** [January 6, 2008, 6:57pm UTC](https://www.ruby-forum.com/t/add-rankings-to-array/125176/2 "2008-01-06T18:57:36Z")

</div>

# 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” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
said:

---

<div class="post-metadata">

**Author:** ![soprano](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b3f665/32.png) [@soprano](https://www.ruby-forum.com/u/soprano)\
**Post date:** [January 6, 2008, 7:11pm UTC](https://www.ruby-forum.com/t/add-rankings-to-array/125176/3 "2008-01-06T19:11:39Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![soprano](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b3f665/32.png) [@soprano](https://www.ruby-forum.com/u/soprano)\
**Post date:** [January 6, 2008, 7:16pm UTC](https://www.ruby-forum.com/t/add-rankings-to-array/125176/4 "2008-01-06T19:16:19Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![soprano](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b3f665/32.png) [@soprano](https://www.ruby-forum.com/u/soprano)\
**Post date:** [January 6, 2008, 8:10pm UTC](https://www.ruby-forum.com/t/add-rankings-to-array/125176/5 "2008-01-06T20:10:51Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![soprano](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b3f665/32.png) [@soprano](https://www.ruby-forum.com/u/soprano)\
**Post date:** [January 6, 2008, 7:45pm UTC](https://www.ruby-forum.com/t/add-rankings-to-array/125176/6 "2008-01-06T19:45:04Z")

</div>

Great, thanks!
