Method: Enumerable#split_at
- Defined in:
- lib/upm/core_ext.rb
#split_at(matcher = nil, options = {}, &block) ⇒ Object
Split this enumerable into chunks, given some boundary condition. (Returns an array of arrays.)
Options:
:include_boundary => true #=> include the element that you're splitting at in the results
(default: false)
:after => true #=> split after the matched element (only has an effect when used with :include_boundary)
(default: false)
:once => flase #=> only perform one split (default: false)
Examples:
[1,2,3,4,5].split{ |e| e == 3 }
#=> [ [1,2], [4,5] ]
"hello\n\nthere\n".each_line.split_at("\n").to_a
#=> [ ["hello\n"], ["there\n"] ]
[1,2,3,4,5].split(:include_boundary=>true) { |e| e == 3 }
#=> [ [1,2], [3,4,5] ]
chapters = File.read("ebook.txt").split(/Chapter \d+/, :include_boundary=>true)
#=> [ ["Chapter 1", ...], ["Chapter 2", ...], etc. ]
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/upm/core_ext.rb', line 67 def split_at(matcher=nil, ={}, &block) include_boundary = [:include_boundary] || false if matcher.nil? boundary_test_proc = block else if matcher.is_a? Regexp boundary_test_proc = proc { |element| element =~ matcher } else boundary_test_proc = proc { |element| element == matcher } end end Enumerator.new do |yielder| current_chunk = [] splits = 0 max_splits = [:once] == true ? 1 : [:max_splits] each do |e| if boundary_test_proc.call(e) and (max_splits == nil or splits < max_splits) if current_chunk.empty? and not include_boundary next # hit 2 boundaries in a row... just keep moving, people! end if [:after] # split after boundary current_chunk << e if include_boundary # include the boundary, if necessary yielder << current_chunk # shift everything after the boundary into the resultset current_chunk = [] # start a new result else # split before boundary yielder << current_chunk # shift before the boundary into the resultset current_chunk = [] # start a new result current_chunk << e if include_boundary # include the boundary, if necessary end splits += 1 else current_chunk << e end end yielder << current_chunk if current_chunk.any? end end |