The Artima Developer Community
Sponsored Link

Ruby Buzz Forum
New Array and Enumerable methods in Ruby 1.9.2: keep_if, chunk...

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Jan Lelis

Posts: 136
Nickname: rbjl
Registered: Aug, 2009

Jan Lelis is an IT student from Dresden/Germany
New Array and Enumerable methods in Ruby 1.9.2: keep_if, chunk... Posted: Jul 5, 2010 8:18 AM
Reply to this message Reply

This post originated from an RSS feed registered with Ruby Buzz by Jan Lelis.
Original Post: New Array and Enumerable methods in Ruby 1.9.2: keep_if, chunk...
Feed Title: rbJ*_*L.net
Feed URL: http://feeds.feedburner.com/rbJL
Feed Description: Hi, I am a fan of Ruby and like to explore it and the world around ;). So I started this blog, where I am publishing code snippets, tutorials for beginners as well as general thoughts about Ruby, the web or programming in general.
Latest Ruby Buzz Posts
Latest Ruby Buzz Posts by Jan Lelis
Latest Posts From rbJ*_*L.net

Advertisement

In Ruby, dealing with Arrays and similar objects is pretty fun. And we have gotten more possibilities with Ruby 1.9.2 :)

The NEWS file says:

  * Array
    * new method:
      * Array#keep_if
      * Array#repeated_combination
      * Array#repeated_permutation
      * Array#rotate
      * Array#rotate!
      * Array#select!
      * Array#sort_by!

    * extended methods:
      * Array#{uniq,uniq!,product} can take a block.
...
  * Enumerable
    * New methods:
      * Enumerable#chunk
      * Enumerable#collect_concat
      * Enumerable#each_entry
      * Enumerable#flat_map
      * Enumerable#slice_before

Let’s take a closer look!

select! and keep_if

The select method (only choose the elements for which the block evaluates to true) got a mutator version select!. It does almost the same like the new keep_if method – with one subtle difference: select! returns nil if no changes were made, keep_if always returns the object.

more combination and permutation

Ruby 1.9 introduced the useful methods combination and permutation. Now there are also repeated_combination and repeated_permutation:

>> [1,2,3].combination(2).to_a
=> [[1, 2], [1, 3], [2, 3]]
>> [1,2,3].repeated_combination(2).to_a
=> [[1, 1], [1, 2], [1, 3], [2, 2], [2, 3], [3, 3]]
>> [1,2,3].permutation(2).to_a
=> [[1, 2], [1, 3], [2, 1], [2, 3], [3, 1], [3, 2]]
>> [1,2,3].repeated_permutation(2).to_a
=> [[1, 1], [1, 2], [1, 3], [2, 1], [2, 2], [2, 3], [3, 1], [3, 2], [3, 3]]

rotate / rotate!

This method removes the first element and appends it. You can pass an integer, how many steps it should “cycle” (negative values are possible). It does something like:

Listing 2
/27/rotate.rb ruby
class Array
  def rotate2(n=1)
    new_start = n % self.size
    self[new_start..-1] + self[0...new_start]
  end
end

small changes: sort_by, uniq / uniq!, product

  • sort_by (the block defines, how the Array should be sorted) also got a mutator version: sort_by!.
  • product (combine all elements from both Arrays) now also accepts a block which yields every result, instead of returning it.
  • uniq (remove duplicates) can now take a block, example from the docs:
Listing 3
/27/uniq_block.rb ruby 1.9
c = [ "a:def", "a:xyz", "b:abc", "b:xyz", "c:jkl" ]
c.uniq {|s| s[/^\w+/]} #=> [ "a:def", "b:abc", "c:jkl" 

flat_map and its alias collect_concat

This method works like map, but if an element is an Enumerable itself, the applied block is also run for each of its child elements (but not recursively).

Listing 4
/27/flat_map.rb ruby 1.9
[[1,2],[3,[4,5]]].flat_map{|i|i} #=> [1, 2, 3, [4,5]]

I do not know (yet), if this is useful (and if it wouldn’t be cooler if it did something like .flatten.map), but we will see…

each_entry

Each entry is like each, but it treats multiple yield arguments as a single array (so yield 1,2 implicitly becomes yield [1,2]). Mostly, the result is similar to eachs, but there are some occasions where it does matter.

chunk

This one is interesting, but it is a little bit strange to use. It splits self into multiple Enumerators, using the rule given in the block. It keeps together those parts that “match” in series. It passes the result of the “filter” rule and an Enumerator of the successive elements – Look at these two examples:

Listing 5
/27/chunk.rb ruby 1.9
(1..42).chunk{|n| n%11 == 0}.each{|result, elements|
  puts "#{result}: #{elements*', '}"
}
# outputs:
# false: 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10
# true: 11
# false: 12 - 13 - 14 - 15 - 16 - 17 - 18 - 19 - 20 - 21
# true: 22
# false: 23 - 24 - 25 - 26 - 27 - 28 - 29 - 30 - 31 - 32
# true: 33
# false: 34 - 35 - 36 - 37 - 38 - 39 - 40 - 41 - 42

# you could (ab)use this to order numbers in quotient rings:
a=(0..4).map{[]}
(1..42).chunk{|n| n%5}.each{|remainder, elements| a[remainder] += elements}
p a
# outputs:
# [[5, 10, 15, 20, 25, 30, 35, 40], [1, 6, 11, 16, 21, 26, 31, 36, 41], [2, 7, 12, 17, 22, 27, 32, 37, 42], [3, 8, 13, 18, 23, 28, 33, 38], [4, 9, 14, 19, 24, 29, 34, 39]]

The chunk block can also return some special values: Symbols that begin with an underscore. Currently, there are two special symbols supported:

  • :_separator (or nil) – the element is dropped
  • :_alone – the element always gets its single chunk

Some advanced examples can be found in the docs.

slice_before

This method also lets you split the Enumerable. You simply specify a pattern/a block which has to match/be true and it splits before that element:

Listing 6
/27/slice_before.rb ruby 1.9
%w|Ruby is 2 parts Perl, 1 part Python, and 1 part Smalltalk|.slice_before(/\d/).to_a
#=> [["Ruby", "is"], ["2", "parts", "Perl,"], ["1", "part", "Python,", "and"], ["1", "part", "Smalltalk"]]

# a more complex version from the docs (slightly modified):
a = [0,2,3,4,6,7,9]
prev = a[0]
a.slice_before {|cur|
  prev, prev2 = cur, prev  # one step further
  prev2 + 1 != prev        # two ago != one ago ? --> new slice
}.to_a
# => [[0], [2, 3, 4], [6, 7], [9]]

What’s next?

It is quite interesting to observe, in which direction Ruby moves with this methods. Some of them where just “missing” previously (e.g. select!). However, some others seem to be for a very special purpose only (chunk) – but maybe it is just a false interpretation on the face of it ;)

CC-BY (DE)

Read: New Array and Enumerable methods in Ruby 1.9.2: keep_if, chunk...

Topic: New Array and Enumerable methods in Ruby 1.9.2 Previous Topic   Next Topic Topic: Ruby, the video

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use