# Problem sorting

**URL:** <https://www.ruby-forum.com/t/problem-sorting/185750>\
**Category:** Ruby\
**Created:** [March 25, 2010, 3:58pm UTC](https://www.ruby-forum.com/t/problem-sorting/185750 "2010-03-25T15:58:37Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![augus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/eb8c5e/32.png) [@augus](https://www.ruby-forum.com/u/augus)\
**Post date:** [March 25, 2010, 3:58pm UTC](https://www.ruby-forum.com/t/problem-sorting/185750/1 "2010-03-25T15:58:37Z")

</div>

I am trying to sort an array using a block but somehow I am not seeing  
what I am want. First I want to sort the total, then break the tie on  
gold goldcount, silvercount and finally on bronzcount

Here is my code. what am I missing? please help

# compare and order by totals

```
    result = b[:total] <=> a[:total]
    # if tied, break the number of gold medals
    result != 0 ? result : b[:goldcount] <=> a[:goldcount]
    result != 0 ? result : b[:silvercount] <=> a[:silvercount]
    result != 0 ? result : b[:bronzcount] <=> a[:bronzcount]
    result != 0 ? result : b[:country] <=> a[:country]

```

end

---

<div class="post-metadata">

**Author:** ![augus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/eb8c5e/32.png) [@augus](https://www.ruby-forum.com/u/augus)\
**Post date:** [March 25, 2010, 4:30pm UTC](https://www.ruby-forum.com/t/problem-sorting/185750/2 "2010-03-25T16:30:57Z")

</div>

At 2010-03-25 10:58AM, “Augusto G.” wrote:

> ```
> result != 0 ? result : b[:silvercount] <=> a[:silvercount]
> result != 0 ? result : b[:bronzcount] <=> a[:bronzcount]
> result != 0 ? result : b[:country] <=> a[:country]
> 
> ```

You’re not assigning the tiebreaker back to the ‘result’ variable

```
# compare

    result = b[:total] <=> a[:total] ||
             b[:goldcount] <=> a[:goldcount] ||
             b[:silvercount] <=> a[:silvercount] ||
             b[:bronzcount] <=> a[:bronzcount] ||
             b[:country] <=> a[:country]

```

It might be clearer to use sort\_by instead of sort

```
sorted = array.sort_by do |h|
  [ 

```

h[:total],h[:goldcount],h[:silvercount],h[:bronzecount],h[:country] ]  
end

---

<div class="post-metadata">

**Author:** ![augus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/eb8c5e/32.png) [@augus](https://www.ruby-forum.com/u/augus)\
**Post date:** [March 25, 2010, 4:32pm UTC](https://www.ruby-forum.com/t/problem-sorting/185750/3 "2010-03-25T16:32:08Z")

</div>

On Thu, Mar 25, 2010 at 3:58 PM, Augusto G. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> ```
> result != 0 ? result : b[:silvercount] <=> a[:silvercount]
> result != 0 ? result : b[:bronzcount] <=> a[:bronzcount]
> result != 0 ? result : b[:country] <=> a[:country]
> 
> ```
> 
> end

I assume you have an array of hashes:

irb(main):001:0\> country\_medals = []  
=\> []

irb(main):002:0\> country\_medals \<\< {:country =\> “Spain”, :total =\>  
100, :goldcount =\> 100, :silvercount =\> 0, :bronzecount =\> 0}  
=\> [{:country=\>“Spain”, :total=\>100, :goldcount=\>100, :silvercount=\>0,  
:bronzecount=\>0}]

irb(main):003:0\> country\_medals \<\< {:country =\> “US”, :total =\> 50,  
:goldcount =\> 50, :silvercount =\> 0, :bronzecount =\> 0}  
=\> [{:country=\>“Spain”, :total=\>100, :goldcount=\>100, :silvercount=\>0,  
:bronzecount=\>0}, {:country=\>“US”, :total=\>50, :goldcount=\>50,  
:silvercount=\>0, :bronzecount=\>0}]

irb(main):004:0\> country\_medals \<\< {:country =\> “UK”, :total =\> 50,  
:goldcount =\> 45, :silvercount =\> 5, :bronzecount =\> 0}  
=\> [{:country=\>“Spain”, :total=\>100, :goldcount=\>100, :silvercount=\>0,  
:bronzecount=\>0}, {:country=\>“US”, :total=\>50, :goldcount=\>50,  
:silvercount=\>0, :bronzecount=\>0}, {:country=\>“UK”, :total=\>50,  
:goldcount=\>45, :silvercount=\>5, :bronzecount=\>0}]

irb(main):010:0\> country\_medals.sort\_by {|x| [-x[:total],  
-x[:goldcount], -x[:silvercount], -x[:bronzecount], x[:country]]}  
=\> [{:country=\>“Spain”, :total=\>100, :goldcount=\>100, :silvercount=\>0,  
:bronzecount=\>0}, {:country=\>“US”, :total=\>50, :goldcount=\>50,  
:silvercount=\>0, :bronzecount=\>0}, {:country=\>“UK”, :total=\>50,  
:goldcount=\>45, :silvercount=\>5, :bronzecount=\>0}]

Jesus.

---

<div class="post-metadata">

**Author:** ![augus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/eb8c5e/32.png) [@augus](https://www.ruby-forum.com/u/augus)\
**Post date:** [March 25, 2010, 6:43pm UTC](https://www.ruby-forum.com/t/problem-sorting/185750/4 "2010-03-25T18:43:20Z")

</div>

Since no one has duplicated what you seemed to be trying:

On Mar 25, 2010, at 11:31 AM, Jesús Gabriel y Galán wrote:

> > ```
> > result = b[:total] <=> a[:total]
> > # if tied, break the number of gold medals
> > result != 0 ? result : b[:goldcount] <=> a[:goldcount]
> > result != 0 ? result : b[:silvercount] <=> a[:silvercount]
> > result != 0 ? result : b[:bronzcount] <=> a[:bronzcount]
> > result != 0 ? result : b[:country] <=> a[:country]
> > 
> > ```
> > 
> > end

.sort {|a,b|  
(b[:total] \<=\> a[:total]).nonzero? ||  
(b[:goldcount] \<=\> a[:goldcount]).nonzero? ||  
(b[:silvercount] \<=\> a[:silvercount]).nonzero? ||  
(b[:bronzcount] \<=\> a[:bronzcount]).nonzero? ||  
b[:country] \<=\> a[:country]  
}

Look at what Numeric#nonzero? is meant for 😉

Also, your original breaks the final tie by reverse sort of the  
country so I do here as well. Augusto has an ascending sort on all and  
Jesús just has an ascending sort on the country.

-Rob

> irb(main):003:0\> country\_medals \<\< {:country =\> “US”, :total =\> 50,  
> :goldcount=\>45, :silvercount=\>5, :bronzecount=\>0}]

Rob B. [http://agileconsultingllc.com](http://agileconsultingllc.com)  
removed\_email\_address@domain.invalid
