[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

sorting an array based on two attributes of objects

senthil

3/26/2007 1:57:00 PM


Thanks for some of your replies for the lst post i need small
modification in that post .. i want to sort the salary in descending
order. i have explained the same quesion again....

Hi all,
I want to sort the objects of array based on two attributes.I want
sort an employee class based on his salary in descecding order and name
, so that if two
person has same salary it should be sorted with name.
Lets say for example the employee objects has following name and
salary.

name salary
d 100
c 200
b 50
a 100


so in this case the result which i expect is

name salary
b 200
a 100
d 100
c 50

Note:In the above example for salary 100 the sorting is done
alphabetically, but initially(before sorting) 'd' came first and then
'a' came.so basically i want to sort the array with more than one order.
Can any one help me to solve it ??

--
Posted via http://www.ruby-....

6 Answers

Alex Young

3/26/2007 2:11:00 PM

0

senthil wrote:
> Thanks for some of your replies for the lst post i need small
> modification in that post .. i want to sort the salary in descending
> order. i have explained the same quesion again....
>
> Hi all,
> I want to sort the objects of array based on two attributes.I want
> sort an employee class based on his salary in descecding order and name
> , so that if two
> person has same salary it should be sorted with name.
> Lets say for example the employee objects has following name and
> salary.
>
> name salary
> d 100
> c 200
> b 50
> a 100
>
>
> so in this case the result which i expect is
>
> name salary
> b 200
> a 100
> d 100
> c 50
>
> Note:In the above example for salary 100 the sorting is done
> alphabetically, but initially(before sorting) 'd' came first and then
> 'a' came.so basically i want to sort the array with more than one order.
> Can any one help me to solve it ??
>
In this case, just invert the salary:

sorted_employees = employees.sort_by { |e| [ -e.salary, e.name ] }

I can't think of a way offhand to have different lexicographic orderings
in the same sort, though.

--
Alex

Ilan Berci

3/26/2007 2:18:00 PM

0

senthil wrote:
>
> Thanks for some of your replies for the lst post i need small
> modification in that post .. i want to sort the salary in descending
> order. i have explained the same quesion again....
>

I came up with this which is sub par as I test for a condition twice so
stay tuned for a better solution..

irb(main):001:0> [['d',100],['c',200],['b',50],['a',100]].sort {|a,b|
b[1]==a[1]?a[0]<=>b[0]:b[1]<=>a[1]}
=> [["c", 200], ["a", 100], ["d", 100], ["b", 50]]

hope this helps

ilan



--
Posted via http://www.ruby-....

Ilan Berci

3/26/2007 2:20:00 PM

0

Alex Young wrote:

>
> sorted_employees = employees.sort_by { |e| [ -e.salary, e.name ] }
>
> I can't think of a way offhand to have different lexicographic orderings
> in the same sort, though.

Doh!!!! Ofcourse! Ok.. more coffee for me..

<sulks away with his tail between his legs>

ilan


--
Posted via http://www.ruby-....

Rob Biedenharn

3/26/2007 3:07:00 PM

0

On Mar 26, 2007, at 10:18 AM, Ilan Berci wrote:
> senthil wrote:
>>
>> Thanks for some of your replies for the lst post i need small
>> modification in that post .. i want to sort the salary in descending
>> order. i have explained the same quesion again....
>>
>
> I came up with this which is sub par as I test for a condition
> twice so
> stay tuned for a better solution..
>
> irb(main):001:0> [['d',100],['c',200],['b',50],['a',100]].sort {|a,b|
> b[1]==a[1]?a[0]<=>b[0]:b[1]<=>a[1]}
> => [["c", 200], ["a", 100], ["d", 100], ["b", 50]]
>
> hope this helps
>
> ilan

Just to add a bit to this: consider using .nonzero? for chained
comparisons

[['d',100],['c',200],['b',50],['a',100]].
sort {|a,b| (b[1]<=>a[1]).nonzero? || a[0]<=>b[0] }

-Rob

Rob Biedenharn http://agileconsult...
Rob@AgileConsultingLLC.com



Rick DeNatale

3/27/2007 4:10:00 PM

0

On 3/26/07, Alex Young <alex@blackkettle.org> wrote:
> senthil wrote:
> > Thanks for some of your replies for the lst post i need small
> > modification in that post .. i want to sort the salary in descending
> > order. i have explained the same quesion again....
> >
> > Hi all,
> > I want to sort the objects of array based on two attributes.I want
> > sort an employee class based on his salary in descecding order and name
> > , so that if two
> > person has same salary it should be sorted with name.
> > Lets say for example the employee objects has following name and
> > salary.
> >
> > name salary
> > d 100
> > c 200
> > b 50
> > a 100
> >
> >
> > so in this case the result which i expect is
> >
> > name salary
> > b 200
> > a 100
> > d 100
> > c 50
> >
> > Note:In the above example for salary 100 the sorting is done
> > alphabetically, but initially(before sorting) 'd' came first and then
> > 'a' came.so basically i want to sort the array with more than one order.
> > Can any one help me to solve it ??
> >
> In this case, just invert the salary:
>
> sorted_employees = employees.sort_by { |e| [ -e.salary, e.name ] }
>
> I can't think of a way offhand to have different lexicographic orderings
> in the same sort, though.

Someone, in another recent thread, came up with the idea of a reverse
proxy class something like this

class Reverse

:attr_reader :obj

def initialize(obj)
@obj = obj
end

def <=>(other)
other.obj <=> self.obj
end

end

so let's say you wanted to sort the names in descending order as well:
sorted_employees = employees.sort_by { |e| [-e.salary, Reverse.new(e.name) ] }

You could even use this "reverse" proxy to change the sorting of
salary, so that the original could be:

sorted_employees = employees.sort_by { |e| [ Reverse.new(e.salary), e.name ] }

One could quibble about the name Reverse.

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denh...

Alex Young

3/27/2007 4:17:00 PM

0

Rick DeNatale wrote:
> On 3/26/07, Alex Young <alex@blackkettle.org> wrote:
<snip>
>> In this case, just invert the salary:
>>
>> sorted_employees = employees.sort_by { |e| [ -e.salary, e.name ] }
>>
>> I can't think of a way offhand to have different lexicographic orderings
>> in the same sort, though.
>
> Someone, in another recent thread, came up with the idea of a reverse
> proxy class something like this
>
> class Reverse
>
> :attr_reader :obj
>
> def initialize(obj)
> @obj = obj
> end
>
> def <=>(other)
> other.obj <=> self.obj
> end
>
> end
>
> so let's say you wanted to sort the names in descending order as well:
> sorted_employees = employees.sort_by { |e| [-e.salary,
> Reverse.new(e.name) ] }
>
> You could even use this "reverse" proxy to change the sorting of
> salary, so that the original could be:
>
> sorted_employees = employees.sort_by { |e| [ Reverse.new(e.salary),
> e.name ] }

That's lovely. My brain wandered off down the String#invert route, and
I ended up getting tied in knots over multibyte encodings. Reverse is a
*much* nicer trick.

--
Alex