Hi,
Here an abstract version of my app, in which I have an array of two-
element arrays I'd like to sort on the second element of each pair
using the spaceship operator:
$data = [ [:A, 12], [:B, 30], [:C, 4] ]
Class MyTest < Array
def <=>(other)
self[1] <=> other[1]
end
@sorted_array = $date
end
How can I make this work?
Thanks in advance,
Richard
|
|
0
|
|
|
|
Reply
|
RichardDummyMailbox58407 (349)
|
4/21/2011 4:13:52 AM |
|
Instead of doing it that way, consider using sort_by instead to sort
by the second element:
ruby-1.9.2-p180 :001 > fruits =3D [[:apple, 100], [:banana, 150],
[:tomato, 80], [:kumquat, 180]]
=3D> [[:apple, 100], [:banana, 150], [:tomato, 80], [:kumquat, 180]]
ruby-1.9.2-p180 :002 > fruits.sort_by { |f| f[1] }
=3D> [[:tomato, 80], [:apple, 100], [:banana, 150], [:kumquat, 180]]
~ jf
--
John Feminella
Principal Consultant, BitsBuilder
LI: http://www.linkedin.com/in/johnxf
SO: http://stackoverflow.com/users/75170/
On Thu, Apr 21, 2011 at 00:15, RichardOnRails
<RichardDummyMailbox58407@uscomputergurus.com> wrote:
> Hi,
>
> Here an abstract version of my app, in which I have an array of two-
> element arrays I'd like to sort on the second element of each pair
> using the spaceship operator:
>
> $data =3D [ [:A, 12], [:B, 30], [:C, 4] ]
>
> Class MyTest < Array
> =C2=A0 =C2=A0def <=3D>(other)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0self[1] <=3D> other[1]
> =C2=A0 =C2=A0end
>
> =C2=A0 =C2=A0@sorted_array =3D $date
> =C2=A0end
>
> How can I make this work?
>
> Thanks in advance,
> Richard
>
>
|
|
0
|
|
|
|
Reply
|
johnf4608 (33)
|
4/21/2011 4:21:00 AM
|
|
RichardOnRails wrote in post #994206:
> Class MyTest < Array
> def <=>(other)
> self[1] <=> other[1]
> end
>
> @sorted_array = $date
> end
>
> How can I make this work?
Your way *can* be made to work, but it's ugly.
class MyElement < Array
def <=>(other)
self[1] <=> other[1]
end
end
a = [ MyElement.new([:A,12]),
MyElement.new([:B,30]),
MyElement.new([:C,4]),
]
a.sort!
p a
The point is that the <=> operator is applied to pairs of elements in
the array, not to the container object itself.
As a general rule I'd say: don't subclass standard Ruby classes. Use
delegation instead. So if you want a container object with Array-like
properties but special behaviour, then make it have an Array, rather
than be an Array.
class MyContainer
def initialize(a = [])
@a = a
end
def sort!
@a = @a.sort_by { |elem| elem[1] }
end
... delegate other methods as required,
... or use SimpleDelegator
end
In the longer term you'll find this a much more flexible way of
composing objects and behaviour. The only reason programming classes
tell you to subclass is because of the inflexible typing systems in
certain other languages.
Ruby has "duck typing": there is no need for your class to inherit from
Array, it just has to implement the behaviour of Array that you're
interested in.
--
Posted via http://www.ruby-forum.com/.
|
|
0
|
|
|
|
Reply
|
b.candler (2627)
|
4/21/2011 9:41:29 AM
|
|
On Apr 21, 12:13=A0am, RichardOnRails
<RichardDummyMailbox58...@USComputerGurus.com> wrote:
> Hi,
>
> Here an abstract version of my app, in which I have an array of two-
> element arrays I'd like to sort on the second element of each pair
> using the spaceship operator:
>
> $data =3D [ [:A, 12], [:B, 30], [:C, 4] ]
>
> Class MyTest < Array
> =A0 =A0 def <=3D>(other)
> =A0 =A0 =A0 =A0 self[1] <=3D> other[1]
> =A0 =A0 end
>
> =A0 =A0 @sorted_array =3D $date
> =A0end
>
> How can I make this work?
>
> Thanks in advance,
> Richard
Hi John and Brian,
Thank you very much for your extremely insightful answers.
I've been oscillating between:
Metaprogramming Ruby
The Well-Oriented Rubyist
Design Patterns in Ruby
But I didn't see anything in them for my sorting problem, so I Googled
for it. Thus I found this concise method, but I couldn't figure out
how to make "self" be my array of arrays.
John: Thanks for that sort_by method using a block to return the
specific value (from each element) I want the sort method to use.
Very tidy!
Brian: Thanks for
1. addressing my key issue about how to make "self" be my array, so to
speak. Question, would that redefinition of <=3D> contaminate uses of
"sort" in other top-level classes? I could test for an answer, but I
might miss something.
2. using "delegation", which I've seen in those textbooks but not yet
internalized.
Best wishes,
Richard
|
|
0
|
|
|
|
Reply
|
RichardDummyMailbox58407 (349)
|
4/21/2011 1:48:31 PM
|
|
Brian Candler wrote in post #994252:
>
> The point is that the <=> operator is applied to pairs of elements in
> the array, not to the container object itself.
>
In other words, your spaceship operator only gets applied to objects of
your class--not any ole' array.
--
Posted via http://www.ruby-forum.com/.
|
|
0
|
|
|
|
Reply
|
bbxx789_05ss (1895)
|
4/21/2011 5:07:30 PM
|
|
RichardOnRails wrote in post #994287:
> Brian: Thanks for
> 1. addressing my key issue about how to make "self" be my array, so to
> speak. Question, would that redefinition of <=> contaminate uses of
> "sort" in other top-level classes?
No. I only redefined <=> within the class MyElement, so it only affects
what happens when you call <=> on an object of class MyElement.
When you call sort on an Array (that is, your outer array which includes
the pairs), internally it does a quicksort. The quicksort calls a.<=>(b)
for various pairs of elements a and b within the array.
So what matters is that the elements *within* the array implement <=>
for comparing themselves against any other element.
> 2. using "delegation", which I've seen in those textbooks but not yet
> internalized.
Basically it means passing through method calls to the underlying
object. You can do this explicitly for each method of interest:
class MyElement
def initialize(a)
@a = a
end
def size
@a.size
end
def [](index)
@a[index]
end
def []=(index,val)
@a[index] = val
end
... etc
end
This gives you an opportunity to customise the behaviour in any way you
like, or have one method call combine the results from invoking multiple
underlying objects, or whatever you like.
If you find it tedious to repeat lots of method definitions, then you
can look at method_missing, or delegate.rb in the Ruby standard library.
There are examples in the source code. In this case:
require 'delegate'
class MyElement < DelegateClass(Array)
def <=>(other)
self[1] <=> other[1]
end
end
This creates a new class which passes all unknown methods to the
underlying object.
a = MyElement.new([:x, :y])
puts a[1]
You have called the '[]' method on your object of class MyElement, and
it's automatically passed through to the '[]' method on the underlying
Array object.
--
Posted via http://www.ruby-forum.com/.
|
|
0
|
|
|
|
Reply
|
b.candler (2627)
|
4/21/2011 5:26:38 PM
|
|
7stud: Thanks for your (comforting :BG) explanation
Brian: Thanks for your expanded explanation
While I'm still playing with delegation, I've taken "ownership" of a
couple of the ideas previously offered, most notably "sort_by" and:
class Meta < Array
def <=>(other)
self[1] <=> other[1]
end
end
a = []
[ [:A,12], [:B,30], [:C,4] ]. each { |element| a <<
Meta.new(element) }
p a.sort
I'm eternally grateful for this website. I'm a retired programmer
relatively new to Ruby and Rails. I'd quit programming except for the
generosity of members of this NG.
Best wishes,
Richard
|
|
0
|
|
|
|
Reply
|
RichardDummyMailbox58407 (349)
|
4/21/2011 11:56:01 PM
|
|
RichardOnRails wrote in post #994401:
> While I'm still playing with delegation, I've taken "ownership" of a
> couple of the ideas previously offered, most notably "sort_by" and:
> class Meta < Array
> def <=>(other)
> self[1] <=> other[1]
> end
> end
>
> a = []
> [ [:A,12], [:B,30], [:C,4] ]. each { |element| a <<
> Meta.new(element) }
> p a.sort
And a slightly tidier way is to use 'map' (aliased as 'collect') which
iterates and accumulates the output array in one go:
a = [ [:A,12], [:B,30], [:C,4] ].map { |element| Meta.new(element) }
p a.sort
Regards,
Brian.
--
Posted via http://www.ruby-forum.com/.
|
|
0
|
|
|
|
Reply
|
b.candler (2627)
|
4/26/2011 10:08:41 AM
|
|
|
7 Replies
35 Views
(page loaded in 0.107 seconds)
Similiar Articles: Getting rid of libstdc++? - comp.unix.programmerIf OTOH you decided to ship a dynamic library, then you can: - link it against ... for __cxxabiv1::__class_type_info vtable for __cxxabiv1::__si_class_type_info operator ... how to calcule the division modulo 2 reminder - comp.sys.hp48 ...HP ship is sinking like Titanic? - comp.sys.hp48... HP49G+ with the ... C# Modulo Operator - Dot Net Perls This C# tutorial shows how to use the modulo division operator. Insert statements and foreign keys etc.. - comp.databases.mysql ...... verification that it really did cancel, did not ship ... type of > logic that attempts to support the operator in ... How to use INSERT INTO Statement in MS Access Database ... ODBC Database Insert 'DateTime' - comp.soft-sys.matlabHello all, I am trying to use an sql query in ... the error [ODBC] Invalid operand for operator ... have applications UPS WorldShip and FedEx Ship Manager connected using ... EMSDIST in TACL script. - comp.sys.tandemIt could be that you misunderstand how to use MATCH, or ... Text: "G112.AA.01.*, started by > operator ... among the token definitions and other SPI files ship ... Estimating engineering time on machine design - comp.cad ...In round numbers, I use 4-5 hours per detail for ... customers, corrected "as built" drawing and full operator ... Any time you "ship money" on a project, you shouldn't ... Inventor V's Solidworks - comp.cad.solidworks... things were so fucked up with MDT. > >jon "Operator ... and Inventor doesn't so we should all jump ship. ... who do reviews of products that they don't know how to use...?" Oracle 10g on HP-UX, Terrible Poor Performance!! - comp.sys.hp ...Depending on the context, vendors may ship SCSI drives with the write cache enable ... related to I/O. following you can > find it: > > ALERT LEVEL: 2 = Non-Urgent operator ... PRINTER - comp.protocols.snmptelegraph bootcamp safe mode printer use telephone ... thermal printers compatible with world ship thermal ... thermal printer operator thermal printer paper and extreme ... C#: Comparison operator overloading and spaceship operator - I ...If C# compiler supports the concept of the space-ship operator then we ... and make the compiler emits calls to it based on the operator getting used or use ... Three-way comparison - Wikipedia, the free encyclopediaIn Perl (numeric comparison only), Ruby, and Groovy, the spaceship operator ("<=>") returns ... Since Java version 1.5, the same can be computed using the Math.signum static ... 7/13/2012 6:03:38 PM
|