# Multiple Sorts on an array, help with bad code smell

**URL:** <https://www.ruby-forum.com/t/multiple-sorts-on-an-array-help-with-bad-code-smell/106906>\
**Category:** Rails\
**Created:** [June 15, 2007, 7:51am UTC](https://www.ruby-forum.com/t/multiple-sorts-on-an-array-help-with-bad-code-smell/106906 "2007-06-15T07:51:36Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![blinking\_bear](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/a9a28c/32.png) [@blinking\_bear](https://www.ruby-forum.com/u/blinking_bear)\
**Post date:** [June 15, 2007, 7:51am UTC](https://www.ruby-forum.com/t/multiple-sorts-on-an-array-help-with-bad-code-smell/106906/1 "2007-06-15T07:51:36Z")

</div>

I have an Array of active record objects that I need to sort by two  
attributes: similarity and activity, both are integers.

I’m currently doing this by first sorting the array on the similarity  
field,  
and then using group\_by to group them groups with the same ‘similarity’  
and  
then sorting those groups by activity. Flattening this whole thing our  
returns the original list sorted first by similarity and then by  
activity.

Problem, this code is ugly, there has to be a cleaner way to do this.  
Here  
is the full method, its from a ActiveRecord model called ‘Group’.

[http://pastie.caboo.se/70645](http://pastie.caboo.se/70645)

def related\_groups  
#get the tags for this group  
tag\_string = tags.collect(&:name)  
#find other groups with same tags  
groups\_with\_same\_tags = Group.find\_tagged\_with(tag\_string)  
if groups\_with\_same\_tags.any?  
#delete self from list of groups  
groups\_with\_same\_tags.delete(self)  
#delete duplicates  
groups\_with\_same\_tags.uniq!  
#count how many tags they have in common (probably could cleanup  
with  
inject)  
groups\_with\_same\_tags.each do |group|  
group.similarity = 0  
tags.each do |tag|  
group.similarity = group.similarity + 1 if group.tags.include  
?(tag)  
end  
end  
#sort based on similarity of tags  
groups\_with\_same\_tags = groups\_with\_same\_tags.sort{ |x,y|  
y.similarity\<=\>  
x.similarity }  
#group into a 2D array grouped by similarity, make sure to  
preserve  
priority of the similarity  
grouped\_groups =  
groups\_with\_same\_tags.group\_by(&:similarity).sort{|x,y|  
y[0] \<=\> x[0]}  
#sort the 2nd dimension of the array(which is an array of the  
items of  
a specific similarity) based on activity  
sorted\_groups = grouped\_groups.collect{ |g| g[1].sort{|x,y|  
y.activity\<=\>  
x.activity }}  
#flatten it out into a 1D array and return  
sorted\_groups.flatten!  
else  
[]  
end  
end

Thanks!

---

<div class="post-metadata">

**Author:** ![blinking\_bear](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/a9a28c/32.png) [@blinking\_bear](https://www.ruby-forum.com/u/blinking_bear)\
**Post date:** [June 15, 2007, 5:54pm UTC](https://www.ruby-forum.com/t/multiple-sorts-on-an-array-help-with-bad-code-smell/106906/2 "2007-06-15T17:54:00Z")

</div>

I haven’t read the detail of your code (yet) but is there some reason  
you can’t form the array with

groups = Group.find(:all, :order =\> “similarity, activity”)

steve

---

<div class="post-metadata">

**Author:** ![blinking\_bear](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/a9a28c/32.png) [@blinking\_bear](https://www.ruby-forum.com/u/blinking_bear)\
**Post date:** [June 15, 2007, 6:12pm UTC](https://www.ruby-forum.com/t/multiple-sorts-on-an-array-help-with-bad-code-smell/106906/3 "2007-06-15T18:12:27Z")

</div>

Steve - Unfortunately not, activity is not stored in the database. It  
is a  
dynamic tally of how many tags it has in common with the original  
object.

thanks

---

<div class="post-metadata">

**Author:** ![blinking\_bear](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/a9a28c/32.png) [@blinking\_bear](https://www.ruby-forum.com/u/blinking_bear)\
**Post date:** [June 15, 2007, 11:20pm UTC](https://www.ruby-forum.com/t/multiple-sorts-on-an-array-help-with-bad-code-smell/106906/4 "2007-06-15T23:20:14Z")

</div>

Try something like:

groups\_with\_same\_tags.sort! { |a, b| a.similarity == b.similarity ?  
b.activity \<=\> a.activity : b.similarity \<=\> a.similarity }

---

<div class="post-metadata">

**Author:** ![blinking\_bear](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/a9a28c/32.png) [@blinking\_bear](https://www.ruby-forum.com/u/blinking_bear)\
**Post date:** [June 16, 2007, 12:18am UTC](https://www.ruby-forum.com/t/multiple-sorts-on-an-array-help-with-bad-code-smell/106906/5 "2007-06-16T00:18:19Z")

</div>

perfect, tests pass, thanks!

---

<div class="post-metadata">

**Author:** ![blinking\_bear](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/a9a28c/32.png) [@blinking\_bear](https://www.ruby-forum.com/u/blinking_bear)\
**Post date:** [June 16, 2007, 10:51pm UTC](https://www.ruby-forum.com/t/multiple-sorts-on-an-array-help-with-bad-code-smell/106906/6 "2007-06-16T22:51:51Z")

</div>

No problem–glad it worked.
