Ruby: Arrays by Example
Arrays are Ruby’s most used collection type. I will use very little description as I give examples for the many different ways to work with Arrays.
Different ways to create an empty Array
[] Array.new Array[] # same as :new Array(nil) # tries converting to an Array first and insures an Array result %w^^ # you can use any character pair-up after the w. content won't need quotes %W^^ # Allows string interpolation
Filling an Array
laughing_pirate = Array.new(3, :arr) # => [:arr, :arr, :arr] [42] * 5 # => [42, 42, 42, 42, 42] [1,2,3].insert(10,8) # position, item ## fills beyond with nil # => [1, 2, 3, nil, nil, nil, nil, nil, nil, nil, 8] x = [1,2,3] x[9] = 10 # just like insert # => [1, 2, 3, nil, nil, nil, nil, nil, nil, 10]
Insertion
[1,2,3,4,5,6].insert 4, :hello # => [1, 2, 3, 4, :hello, 5, 6] x = [1,2,3,4,5,6,7,8] x[2,4] = :hello # slice replacement x # => [1, 2, :hello, 7, 8] x[2,2] = [3,4,5,6] # slice replacement x # => [1, 2, 3, 4, 5, 6, 8] x[2] = [8,7] # creates inner array x # => [1, 2, [8, 7], 4, 5, 6, 8] x[1..4] = [7] # range slice insertion x # => [1, 7, 6, 8]
Boolean/Truthiness
[false, false, false].all? # => false [true, false, false].all? # => false [true, true, true].all? # => true [false, false, false].any? # => false [false, true, false].any? # => true [1,2,3,4].all?(&:even?) # => false [1,2,3,4].any?(&:even?) # => true [1,2,3,4].any? {|item| item > 2 && item < 4} # => true [1,2,3,4].one? # => false [4].one? # => true [1,2,3,4].one?(&:even?) # => false [1,2,3].one?(&:even?) # => true [1,2,3].empty? # => false [].empty? # => true [1,2,3].include? 5 # => false [1,2,3].frozen? # => false [1,2,3].eql? [1,2] # => false [1,2,3].== [1,2] # => false
Transformations
# zip ['H', 'l', 'o', 'o', 'l'].zip( ['e', 'l', 'W', 'r', 'd'] ) # => [["H", "e"], ["l", "l"], ["o", "W"], ["o", "r"], ["l", "d"]] # transpose [["H", "e"], ["l", "l"], ["o", "W"], ["o", "r"], ["l", "d"]].transpose # => [["H", "l", "o", "o", "l"], ["e", "l", "W", "r", "d"]] # product [:a,:b,:c].product [1,2,3] # => [[:a, 1], [:a, 2], [:a, 3], [:b, 1], [:b, 2], [:b, 3], [:c, 1], [:c, 2], [:c, 3]] # combination (no repetitions of pairings) [:a,:b,:c,:d].combination(2).to_a # => [[:a, :b], [:a, :c], [:a, :d], [:b, :c], [:b, :d], [:c, :d]] # permutation (will give both [a,b] and [b,a]) [:a,:b,:c].permutation(2).to_a # => [[:a, :b], [:a, :c], [:b, :a], [:b, :c], [:c, :a], [:c, :b]] # reverse and reverse! [1,2,3].reverse # => [3, 2, 1] # sort and sort! [2,1,3].sort # => [1, 2, 3] # shuffle and shuffle! [1,2,3].shuffle # => [3, 1, 2] # uniq and uniq! [2,1,3,3,1,2].uniq # => [2, 1, 3] # rotate and rotate! [:a,:b,:c].rotate # => [:b, :c, :a] # compact and compact! [:a,:b,nil,nil,nil,:c].compact # => [:a, :b, :c] # flatten and flatten! [["H", "e"], ["l", "l"], ["o", "W"], ["o", "r"], ["l", "d"]].flatten # => ["H", "e", "l", "l", "o", "W", "o", "r", "l", "d"]
Slicing
# slice and slice! [1,2,3,4,5,6,7,8].slice(2) # => 3 [1,2,3,4,5,6,7,8][2] # => 3 [1,2,3,4,5,6,7,8].slice(2..5) # => [3, 4, 5, 6] [1,2,3,4,5,6,7,8][2..5] # => [3, 4, 5, 6] [1,2,3,4,5,6,7,8].slice(2,5) # => [3, 4, 5, 6, 7] [1,2,3,4,5,6,7,8][2,5] # => [3, 4, 5, 6, 7] # Enumerables [8,7,6,5,4,3,2,1].slice_after(2).to_a # => [[8, 7, 6, 5, 4, 3, 2], [1]] [8,7,6,5,4,3,2,1].slice_before(2).to_a # => [[8, 7, 6, 5, 4, 3], [2, 1]] [1,2,4,9,10,11,12,15,16,19,20,21].slice_when {|i,j| i+1 != j}.to_a # => [[1, 2], [4], [9, 10, 11, 12], [15, 16], [19, 20, 21]]
Adding
[2,3,4] + [5,6,7] # => [2, 3, 4, 5, 6, 7] [2,3,4] << [5,6,7] # => [2, 3, 4, [5, 6, 7]] [2,3,4] .concat [5,6,7] # => [2, 3, 4, 5, 6, 7] [2,3,4] .unshift [5,6,7] # => [[5, 6, 7], 2, 3, 4] [2,3,4] .push [5,6,7] # => [2, 3, 4, [5, 6, 7]] [2,3,4] | [3,4,5,6,7] # => [2, 3, 4, 5, 6, 7]
Replace & Remove
[2,3,4] .replace [4,5,6] # => [4, 5, 6] x = [1,2,3,4,5] x.pop # => 5 x # => [1, 2, 3, 4] x.shift # => 1 x # => [2, 3, 4] x.clear # => [] x = [1,2,3,4,5] x.delete(2) # => 2 x # => [1, 3, 4, 5] x.delete_at(3) # => 5 x # => [1, 3, 4] [1,2,3,4,5,6,7,8].delete_if(&:even?) # => [1, 3, 5, 7] [1,2,3,4,5,6,7,8].delete_if {|n| n.even? && n > 4} # => [1, 2, 3, 4, 5, 7] [1,2,3,4,5,6,7,8].keep_if(&:odd?) # => [1, 3, 5, 7] [:a,:b,:c,:d,:e] - [:a,:e] # => [:b, :c, :d]
Selecting
# Already covered are keep_if, delete_if, slice, [] [1,2,3,4,5,6,7,8].select(&:even?) # => [2, 4, 6, 8] [1,2,3,4,5,6,7,8].select {|n| n < 3 || n > 5} # => [1, 2, 6, 7, 8] [1,2,3,4,5,6,7,8].detect(&:even?) # Detect gets first truth result # => 2 [1,2,3,4,5,6,7,8].values_at(2) # => [3] [1,2,3,4,5,6,7,8].values_at(2,4) # => [3, 5] [1,2,3,4,5,6,7,8].values_at(2,4,5) # => [3, 5, 6] [1,2,3,4,5,6,7,8].values_at(2..5) # => [3, 4, 5, 6] # reject and reject! [1,2,3,4,5,6,7,8].reject(&:even?) # => [1, 3, 5, 7] [1,2,3,4,5,6,7,8].find {|i| i.even?} # => 2 [1,2,3,4,6,8,9,11,13,14,15,16].chunk(&:even?).to_a # => [[false, [1]], [true, [2]], [false, [3]], [true, [4, 6, 8]], [false, [9, 11, 13]], [true, [14]], [false, [15]], [true, [16]]] [1,2,3,4,5,6,7,8].take(3) # => [1, 2, 3] [1,2,3,4,5,6,7,8].group_by(&:even?) # => {false=>[1, 3, 5, 7], true=>[2, 4, 6, 8]} [2,3,4] .partition {|i| i.even?}.to_a # => [[2, 4], [3]] [0,1,2,3,4,5,6,7,9].group_by.with_index {|_,index| index % 4 }.values # => [[0, 4, 9], [1, 5], [2, 6], [3, 7]]
Mapping
[1,2,3,4,5,6,7,8].map {|n| n.even? ? n*4 : [n]} # => [[1], 8, [3], 16, [5], 24, [7], 32] [1,2,3,4,5,6,7,8].flat_map {|n| n.even? ? n*4 : [n]} # => [1, 8, 3, 16, 5, 24, 7, 32] [1,2,3,4,5,6,7,8].collect_concat {|n| n.even? ? n*4 : [n]} # => [1, 8, 3, 16, 5, 24, 7, 32]
Reduce with compounded result
[1,2,3,4,5,6,7,8].reduce(:+) # => 36 [1,2,3,4,5,6,7,8].inject(:+) # => 36 [1,2,3,4,5,6,7,8].inject(:*) # => 40320 x.reduce({}) {|hash, a| hash[a.even?] = Array(hash[a.even?]) << a ; hash} # => {false=>[1, 3, 5, 7], true=>[2, 4, 6, 8]} x.inject({}) {|hash, a| hash[a.even?] = Array(hash[a.even?]) << a ; hash} # => {false=>[1, 3, 5, 7], true=>[2, 4, 6, 8]}
Counting
[1,2,3,4,5].count # => 5 [1,2,3,4,5].count(&:odd?) # => 3 ["Ah","Ac","2c"].count {|c| c[0] == "A"} # => 2
Array()
class Example def to_ary puts "to_ary called" [] end def to_a puts "to_a called" [] end end Array(Example.new) #to_ary called # => [] class Example undef :to_ary end Array(Example.new) #to_a called # => [] class Example undef :to_a end Array(Example.new) # => [#<Example:0x00000000a72880>]
As you can see Array() tries to call to_ary first, to_a if that doesn’t work, and just wraps the object in an Array if neither of those methods are defined.
The Ws
cow = "moo" %w^ 1 2 3 #{cow} 4 5 6^ # => ["1", "2", "3", "\#{cow}", "4", "5", "6"] %W^ 1 2 3 #{cow} 4 5 6^ # => ["1", "2", "3", "moo", "4", "5", "6"] %w[] # => [] %w{} # => [] %w() # => [] %W("a" 'b' c' "d) # => ["\"a\"", "'b'", "c'", "\"d"]
As you can see the Ws are great if you want to have either kind of quotation marks within your string items.
In closing
In all of the examples above I’ve shown the output but haven’t explicitly revealed whether the methods change the Array they’re called on or just return an Array result. Please experiment for yourself in an irb terminal to find out more. Typically any method ending with an exclamation point (!) changes the Array itself.
Feel free to check out my other related posts on Different Collection Types in Ruby, When to use Ampersand and/or Colon with Proc, Map, and Inject , and comment any useful Array method usages and tricks! I may add more examples for Array here so be sure to check back!
As always I hope you’ve enjoyed this! Please comment, share, subscribe to my RSS Feed, and follow me on twitter @6ftdan!
God Bless!
-Daniel P. Clark
Image by Tom Blackwell via the Creative Commons Attribution-NonCommercial 2.0 Generic License
digitalhub
January 18, 2016 - 3:11 pm
Fantastic resource! Bookmarked
Ketan Shukla
March 31, 2016 - 11:28 am
This is such a fantastic article! Worthy of being bookmarked for reference! Thank you for this Dan!
Daniel P. Clark
March 31, 2016 - 12:00 pm
You’re very welcome 🙂
Cameron Seright
September 26, 2016 - 12:08 pm
Amazing resource, I learned so much! Thank you, Daniel. Here I was thinking I knew Arrays well =]