<% "A".upto("Z") do |c| %> <li <%= 'class="current"' if (session['wordlist'] == c.downcase) %>> <%= link_to '<span>' + c + '</span>', {:action => 'list', :character => c.downcase} %> </li> <% end %>
@words = Word.find(:all, :conditions => [" root LIKE CONCAT('%',CONCAT(:keyword,'%')) ", {:keyword => keyword}])
This code adds a ”/” instance method to the Array class.
class Array def / pieces len = self.length; mid = (len/pieces) chunks = [] start = 0 1.upto(pieces) do |i| last = start+mid last = last-1 unless len%pieces >= i chunks << self[start..last] || [] start = last+1 end chunks end end
(I didn't invent this myself, but I've lost the url to the original code. If you're the author, or you know the author, please contact me and I'll put in a link here).
Suppose you have a an array of words which you want to output in two columns. Here's how to do this, using our ”/” method:
left, right = *(@words / 2)
The “*” operator is called the splat operator, or sometimes the splash operator. As is explained here the splat operator takes an array and pulls the contents out of the array. You can use the splat operator to simplify this code:
why = [:lucky, :stiff, :with, :chunky, :bacon] v1 = why[0] v2 = why[1] v3 = why[2] v4 = why[3] v5 = why[4]
To this code:
why = [:lucky, :stiff, :with, :chunky, :bacon] v1,v2,v3,v4,v5 = *why
Update (20071104): the splat / splash operator returns a copy. Otherwise, a reference is returned. In other words, this code – without splat/splash – will also work:
why = [:lucky, :stiff, :with, :chunky, :bacon] v1,v2,v3,v4,v5 = why
I can't find a real difference between using the splat/splash operator, and not using it, though:
irb(main):001:0> a = Array.new() => [] irb(main):002:0> a.push(:first) => [:first] irb(main):003:0> a.push(:second) => [:first, :second] irb(main):004:0> my_first,my_second = a => [:first, :second] irb(main):005:0> puts "my_first: #{my_first}" my_first: first => nil irb(main):006:0> my_first.equal?(a[0]) => true irb(main):007:0> my1, my2 = *a => [:first, :second] irb(main):008:0> puts "my1: #{my1}" my1: first => nil irb(main):009:0> my1.equal?(a[0]) => true irb(main):010:0> b = ['e1','e2'] => ["e1", "e2"] irb(main):011:0> split_a1, split_a2 = b => ["e1", "e2"] irb(main):012:0> split_a1.equal?(b[0]) => true irb(main):013:0> split_b1, split_b2 = *b => ["e1", "e2"] irb(main):014:0> split_b1.equal?(b[0]) => true
This seems to indicate that a reference is returned in all cases.
The Array object comes with various handy methods, such as collect
or select
to create a subset. But recently I ran into a problem: how do you return all elements up till and including the element that meets your search criteria?
Usually this is not very hard. If your set is ordered by some criterion, you just use select
:
# Find all future rock concerts scheduled_concerts = rock_concerts.select {|rc| rc.date > Date.today}
But now suppose that your set is ordered, but by many criteria. Of course, you could use multiple conditions in the body of the select
method. But now suppose that you already have the id of the object which is your right limit. The following code snippet exemplifies this:
@completed_exercises = Array.new if (not @saved_game.nil?) @scheduled_exercises.each do |s| @completed_exercises.push(s.id) break if s.id == @saved_game.scheduled_exercise_id end end
Here, I needed both the entire set of available exercises (@scheduled_exercises, retrieved elsewhere), as well as the set of completed exercises (@completed_exercises).