I am using case in to determine the sorting method used for an array as
so:
def single_choice(object)
# sort answer order based on question.list_method
answers = object.answers
sorted_answers = case object.list_method
when 'position' then answers.sort_by {|answer| answer.position}
when 'random' then answers.sort_by {rand}
when 'alphabetical' then answers.sort_by {|answer| answer.text}
when 'reverse_alpha' then answers.sort_by {|answer| answer.text}
return answers.reverse
when 'shortest_first' then answers.sort_by {|answer|
answer.text.length}
when 'longest_first' then answers.sort_by {|answer|
answer.text.length}
return answers.reverse
end
This does not because of the return statements. However, I need to
reverse the result for those two options. How can I do this with case
statements? Or must I use if..elsif?
# sort answer order based on question.list_method
answers = object.answers
sorted_answers = case object.list_method
when 'position' then answers.sort_by {|answer| answer.position}
when 'random' then answers.sort_by {rand}
when 'alphabetical' then answers.sort_by {|answer| answer.text}
when 'reverse_alpha' then answers.sort_by {|answer| answer.text}.reverse
when 'shortest_first' then answers.sort_by {|answer| answer.text.length}
when 'longest_first' then answers.sort_by {|answer|
answer.text.length}.reverse
end
end
Jesus.
···
On Wed, Jan 14, 2009 at 4:56 PM, Taylor Strait <taylorstrait@gmail.com> wrote:
I am using case in to determine the sorting method used for an array as
so:
This does not because of the return statements. However, I need to
reverse the result for those two options. How can I do this with case
statements? Or must I use if..elsif?
when 'reverse_alpha' then answers.sort_by {|answer| answer.text}
return answers.reverse
What you're doing here may be clearer if you write it out like this:
when 'reverse_alpha'
answers.sort_by {|answer| answer.text}
return answers.reverse
What's happening is (1) the answers.sort_by... line is creating a new
sorted array - and then discarding this array. (2) The last line then
returns the original 'answers' array, reversed.
You could fix this by:
when 'reverse_alpha'
answers.sort_by {|answer| answer.text}.reverse
The value of this whole expression becomes the value result of the case
statement, which in turn becomes the return value of the method.
If you really did need to use 'return' to drop straight out of the
method, you could do
when 'reverse_alpha'
answers = answers.sort_by {|answer| answer.text}
return answers.reverse
Or just:
when 'reverse_alpha'
return answers.sort_by {|answer| answer.text}.reverse
I don't mean to be too intrusive as I am a dreadful IT Recruiter that
you probably all despise. I am working on filling a number of RoR
Developer positions(beginners are welcomed) for an exciting young
company in NYC. If you are interested in learning more about the
position please e-mail me, mmartino@apexsystemsinc.com or call me at
212.991.1835. No one has to
know that you contacted me regarding and you can still bash me here in
the blog.
Have a great day! Thanks!
Taylor Strait wrote:
···
I am using case in to determine the sorting method used for an array as
so:
def single_choice(object)
# sort answer order based on question.list_method
answers = object.answers
sorted_answers = case object.list_method
when 'position' then answers.sort_by {|answer| answer.position}
when 'random' then answers.sort_by {rand}
when 'alphabetical' then answers.sort_by {|answer| answer.text}
when 'reverse_alpha' then answers.sort_by {|answer| answer.text}
return answers.reverse
when 'shortest_first' then answers.sort_by {|answer|
answer.text.length}
when 'longest_first' then answers.sort_by {|answer|
answer.text.length}
return answers.reverse
end
This does not because of the return statements. However, I need to
reverse the result for those two options. How can I do this with case
statements? Or must I use if..elsif?
To go a step further than just answering your question, I'd refactor the
whole function like this :
def single_choice(object)
l = case object.list_method
when /^position/ then lambda { |x| x.position }
when /^rand/ then lambda { rand }
when /^alpha/ then lambda { |x| x.to_s }
when /^length/ then lambda { |x| x.length }
end
sorted_answers = object.answers.sort_by(&l)
if order =~ /desc$/
sorted_answers.reverse!
end
sorted_answers
end
The lamba is there to avoid the repetition of the sort_by calls, the use
of regexpen means you have to standardize your methods (length and
length_desc vs shortest_firts and longest_first). On the other hand,
you can manage all kind of sorts without duplicating your sort method.
An even nicer form, if your arrays are of a manageable size, would be :
def single_choice(object)
r = (object.list_method =~ /desc/ ? -1 : 1)
l = case object.list_method
when /^position/ then lambda { |x, y| (x.position <=> y.position) * r }
when /^rand/ then lambda { rand }
when /^alpha/ then lambda { |x, y| (x.to_s <=> y.to_s) * r }
when /^length/ then lambda { |x, y| (x.length <=> y.length) * r }
end
object.answers.sort(&l)
end
(But sort is slower for big arrays.)
You can also extract the case expression into a helper method if you
need to sort other kinds of objects...
HTH,
Fred
···
Le 14 janvier 2009 à 16:56, Taylor Strait a écrit :
This does not because of the return statements. However, I need to
reverse the result for those two options. How can I do this with case
statements? Or must I use if..elsif?
--
"- Anyway, United Amalgamated Consolidated Holdings probablt don't worry
about that sort of thing. They've probabbly got a Vice-President in
Charge of Being Cursed. - And he probably gets his secretary to deal
with it." (Terry Pratchett, Johnny and the Dead)
To go a step further than just answering your question, I'd refactor the
whole function like this :
def single_choice(object)
l = case object.list_method
when /^position/ then lambda { |x| x.position }
when /^rand/ then lambda { rand }
when /^alpha/ then lambda { |x| x.to_s }
when /^length/ then lambda { |x| x.length }
end
sorted_answers = object.answers.sort_by(&l)
if order =~ /desc$/
sorted_answers.reverse!
end
sorted_answers
end
That is great usage of regex's -- thanks for showing me that!
Well, you are not reversing the code block, you are reversing the
result of the call to sort_by, which is an array.
The line is functionally identical to:
(answers.sort_by {|answer| answer.text}).reverse
The sort_by method receives no params and a block, and returns an
array. You are then calling reverse on the resulting array.
It's more clear in Brian's explanation, where he used a temporary
variable to store the result of the sort_by call.
Hope this clarifies,
Jesus.
···
On Wed, Jan 14, 2009 at 5:26 PM, Taylor Strait <taylorstrait@gmail.com> wrote:
Thanks Brian and Jesus - I didn't know you could .reverse a code block.
I had tried that with parenthesis but not just on the block itself.