switch_around
1 2 require 'enumerator' 3 4 # Returns an object of the argument's class with each_slice of 2 switched around. 5 # Works on any object that mixes in #each 6 # 7 # Examples: 8 # switch_around("foo!") #=> of!o 9 # switch_around((1..10).to_a) #=> [2, 1, 4, 3, 6, 5, 8, 7, 10, 9] 10 def switch_around(data) 11 switched_data = data.class.new 12 13 # When appending to a string ints will have #chr called on them, so protect against 14 # error about sending a message to nil. b will only be nil when the collection is 15 # an odd length. Of course, this creates a bug. For example we could have an Array with 16 # embedded nils, so we must also check if it is a String (again...) 17 switch_proc = lambda do |a,b| 18 switched_data << b unless b.nil? and data.is_a?(String) 19 switched_data << a 20 end 21 22 # String#each enumerates over lines, so we must change it to enumerate over bytes. 23 if data.is_a?(String) 24 data.to_enum(:each_byte).each_slice(2) { |a,b| switch_proc.call(a, b) } 25 else 26 data.each_slice(2) { |a,b| switch_proc.call(a,b) } 27 end 28 29 switched_data 30 end