Class: Array
- Includes:
- RMTools::SmarterSetOps
- Defined in:
- lib/rmtools/enumerable/array_iterators.rb,
lib/rmtools/rand/array.rb,
lib/rmtools/dev/present.rb,
lib/rmtools/core/arguments.rb,
lib/rmtools/enumerable/array.rb
Overview
- 1, 2, 3].to_ss # => [‘1’, ‘2’, ‘3’
-
[[1,2,3], [4,5,6], [7,8,9]].to_sss
> [[“1”, “2”, “3”], [“4”, “5”, “6”], [“7”, “8”, “9”]]
[[“1”, “2”, “3”], [“4”, “5”, “6”], [“7”, “8”, “9”]].subss!(/d+/) {|m| (m.to_i % 3).to_s}
> [[“1”, “2”, “0”], [“1”, “2”, “0”], [“1”, “2”, “0”]]
[[1, 2, 0], [1, 2, 0], [1, 2, 0]].sum_zeros?
> [false, false, true, false, false, true, false, false, true]
[[1, 2, 3], [3, 4, 6], [3, 8, 0]].uniq_by_odds?
> [[1, 2, 3], [3, 4, 6]]
Direct Known Subclasses
Constant Summary collapse
- @@iterators_names =
[]
Class Method Summary collapse
- .add_iterator_name(name_or_list) ⇒ Object
- .fallback_to_clean_iterators! ⇒ Object
- .method_defined?(method, *private) ⇒ Boolean
-
.object_method_defined? ⇒ Object
def fallback_to_clean_iterators!.
- .rand(len) ⇒ Object
-
.simple_inplace_singularize!(noun) ⇒ Object
It’s here just because it’s simplier and faster (40 times) than ActiveSupport’s singularization.
- .use_active_support_singularize! ⇒ Object
Instance Method Summary collapse
-
#===(obj) ⇒ Object
making multiple pattern matching possible: a, b = ‘3’, ‘10’ case [a, b] when [Integer, Integer]; a+b when [/d/, ‘10’]; ‘%*d’%[a, b] …
-
#>>(ary) ⇒ Object
concatenation analogy of String#>>.
-
#arrange(*args) ⇒ Object
Make hash with unique items of
self
or (when block given) unique results of items yield for keys and count of them inself
, or (with option :fill) arrays of yield results, or (with option :indexes) arrays of indexes of them, or (with option :group) arrays of themselves for values. -
#arrange_by(*args, &block) ⇒ Object
C-function, see it in /ext.
-
#as_box(opts = {}) ⇒ Object
draw array as box just calls #inspect if max element.inspect size is greater than console width.
-
#avg ⇒ Object
arithmetics.
-
#avg_by(&block) ⇒ Object
for use with iterators.
- #casecmp ⇒ Object
- #del_all_where(&block) ⇒ Object
- #del_where(&block) ⇒ Object
-
#div(int, to_int_parts = nil) ⇒ Object
splitters.
- #div!(int, to_int_parts = nil) ⇒ Object
-
#each_two ⇒ Object
yield every unique combination of two elements.
- #evens ⇒ Object
-
#every? ⇒ Boolean
conditional.
-
#fetch_opts(defaults = [], opts = {}) ⇒ Object
(also: #get_opts)
a, b, opts = [<hash1>].fetch_opts([<hash2>, <object1>]) may work unintuitive: you’ll get <hash1> as ‘a’ and not as ‘opts’ So if function is not implying that some argument other than ‘opts’ definetly must be a hash, don’t make hash default.
-
#find_by(key, value) ⇒ Object
find-by-value filters It’s more of a pattern.
-
#group_by(&b) ⇒ Object
fastering activesupport’s method.
- #index_where(&block) ⇒ Object (also: #pos)
- #indices_map ⇒ Object (also: #addresses)
- #indices_where(&block) ⇒ Object
-
#map_with_index(&block) ⇒ Object
enumerating.
- #no? ⇒ Boolean
-
#odds ⇒ Object
filters.
-
#partition {|obj| ... } ⇒ Array
Same as Enumerable#partition, but twice faster.
- #partition_by(key, value) ⇒ Object
- #present(inspect_string = nil) ⇒ Object
- #rand ⇒ Object
- #rand! ⇒ Object
- #rand_by ⇒ Object
- #randdiv(int) ⇒ Object
- #randdiv!(int) ⇒ Object
- #reject_by(key, value) ⇒ Object
-
#rfind ⇒ Object
rightmost #find.
-
#rfind_by(key, value) ⇒ Object
rightmost #find_by.
-
#runiq ⇒ Object
rightmost #uniq.
-
#runiq_by(&block) ⇒ Object
rightmost #uniq_by.
- #scale(top) ⇒ Object
- #select_by(key, value) ⇒ Object
- #set_all_where(value, &block) ⇒ Object
-
#set_where(value, &block) ⇒ Object
setters/getters/deleters.
- #sort_along_by(ary) ⇒ Object (also: #order_by)
-
#sorted_uniq_by(&block) ⇒ Object
sort / group.
-
#stranspose ⇒ Object
puts [‘123’, ‘456’, ‘789’].stranspose 147 258 369.
-
#sum(identity = 0, &b) ⇒ Object
mapreduce.
- #throw_no ⇒ Object
-
#turn_ccw ⇒ Object
puts [‘123’, ‘456’, ‘789’].turn_ccw 369 258 147.
-
#turn_cw ⇒ Object
puts [‘123’, ‘456’, ‘789’].turn_cw 147 258 369.
-
#uniq? ⇒ Boolean
uniqs.
- #valid_types(pattern_ary) ⇒ Object
Methods included from RMTools::SmarterSetOps
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args, &block) ⇒ Object (private)
Benchmark 3:
# 3.2. Meta calls: # 3.2.1: = (13 * 10^6 x #__send__) timer(1_000_000) { [[1, 2, 3], [3, 4, 6], [3, 8, 0]].uniq_by_odds? } one: 0.0145ms, total: 14520.0ms # = 11% of time a = (0…300).to_a.map 300; # 3.2.2: = (9 * 10^6 x #__send__) timer(100) { a.uniq_by_odds? } one: 36.1000ms, total: 3610.0ms # = 6% of time
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 |
# File 'lib/rmtools/enumerable/array_iterators.rb', line 260 def method_missing(method, *args, &block) if match = (meth = method.to_s).match(@@iterators_pattern) iterator, meth = match[1], match[2] iterator.sub!(/^((?:ever|an)y|no(?:ne)?)$/, '\1?') iterator = iterator.to_sym case iterator when :sum, :sort_along_by, :order_by # sum_posts_ids([], :all) => # sum([]) {|e| e.posts_ids(:all)} Array.class_eval %{ def #{method}(*args, &block) #{iterator}(args.shift) {|e| e.#{meth}(*args, &block)} rescue NoMethodError => err err.message << " (`#{method}' interpreted as decorator-function `#{meth}')" raise err end} when :find_by, :rfind_by, :select_by, :reject_by, :partition_by # select_by_count(max_count) => # select {|e| e.count == max_count} Array.class_eval %{ def #{method}(val) #{iterator.to_s[0...-3]} {|e| e.#{meth} == val} rescue NoMethodError => err err.message << " (`#{method}' interpreted as decorator-function `#{meth}')" raise err end} when :fold, :foldl, :foldr # fold_responders(:|, []) => # fold(:|, []) {|e| e.responders} Array.class_eval %{ def #{method}(*args, &block) #{iterator}(*args[0, 2]) {|e| e.#{meth}(*args[2..-1], &block)} rescue NoMethodError => err err.message << " (`#{method}' interpreted as decorator-function `#{meth}')" raise err end} else # uniq_by_sum(1) {|i| 1 / i.weight} => # uniq_by {|e| e.sum(1) {|i| 1 / i .weight}} Array.class_eval %{ def #{method}(*args, &block) #{iterator} {|e| e.#{meth}(*args, &block)} rescue NoMethodError => err err.message << " (`#{method}' interpreted as decorator-function `#{meth}')" raise err end} end elsif simple_inplace_singularize!(meth) assignment = meth =~ /=$/ meth = meth.to_sym if assignment # if Array === value # owner_ids = users_ids => # each_with_index {|e, i| e.owner_id = users_ids[i]} # else # owner_ids = user_id => # each {|e, i| e.owner_id = user_id} Array.class_eval %{ def #{method}(value) if Array === value each_with_index {|e, i| e.#{meth} value[i]} else each {|e| e.#{meth} value} end rescue NoMethodError => err err.message << " (`#{method}' interpreted as map-function `#{meth}')" raise err end} else # to_is(16) => # map {|e| e.to_i(16)} Array.class_eval %{ def #{method}(*args, &block) map {|e| e.#{meth}(*args, &block)} rescue NoMethodError => err err.message << " (`#{method}' interpreted as map-function `#{meth}')" raise err end} end else return throw_no method end __send__(method, *args, &block) end |
Class Method Details
.add_iterator_name(name_or_list) ⇒ Object
40 41 42 43 44 |
# File 'lib/rmtools/enumerable/array_iterators.rb', line 40 def add_iterator_name(name_or_list) name_or_list = [name_or_list] if !name_or_list.is Array @@iterators_names |= name_or_list @@iterators_pattern = %r{^(#{@@iterators_names*'|'})_([\w\d\_]+[!?]?)} end |
.fallback_to_clean_iterators! ⇒ Object
54 55 56 57 58 59 60 61 62 63 64 65 66 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 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/rmtools/enumerable/array_iterators.rb', line 54 def fallback_to_clean_iterators! class_eval do # Benchmark 1: # # We take a simple methods like uniq_by (O(N)) and odd? (O(1)) to ensure that # # penalty we would have in production would not be larger than that in bench # # # 1.1. Traditional calls: # # 1.1.1: (9 x #odd? + 3 x #map + 1 x #uniq_by) * 10^6 # timer(1_000_000) { [[1, 2, 3], [3, 4, 6], [3, 8, 0]].uniq_by {|i| i.map {|j| j.odd?}} } # one: 0.0130ms, total: 13040.0ms # # 1.1.2: (90_000 x #odd? + 300 x #map + 1 x #uniq_by) * 100 # timer(100) { a.uniq_by {|i| i.map {|j| j.odd?}} } # one: 34.0000ms, total: 3400.0ms # # # 1.2. Meta calls: # # 1.2.1: += (13 * 10^6 x #__send__) + (4 * 10^6 x #method_missing) # timer(1_000_000) { [[1, 2, 3], [3, 4, 6], [3, 8, 0]].uniq_by_odds? } # one: 0.0354ms, total: 35440.0ms # # += 172% of time # a = (0...300).to_a.map {Array.rand 300}; # # 1.2.2: += (9 * 10^6 x #__send__) + (30_100 x #method_missing) # timer(100) { a.uniq_by_odds? } # one: 39.3000ms, total: 3930.0ms # # += 16% of time # # Conclusion: # # 1. If we want to speed meta-calls up, we should sacrifice cleanness of Array namespace, # I mean define missing methods inplace. # 2. Most latency is given by #method_missing, but which are factor of #__send__? def method_missing(method, *args, &block) if match = (meth = method.to_s).match(@@iterators_pattern) iterator, meth = match[1], match[2] iterator.sub!(/^((?:ever|an)y|no(?:ne)?)$/, '\1?') iterator = iterator.to_sym begin return case iterator when :sum, :sort_along_by __send__(iterator, args.shift) {|i| i.__send__ meth, *args, &block} when :find_by, :select_by, :reject_by, :partition_by __send__(iterator, meth, *args) when :fold, :foldl, :foldr __send__(iterator, *args[0, 2]) {|e| e.__send__ meth, *args[2..-1], &block} else __send__(iterator) {|i| i.__send__ meth, *args, &block} end rescue NoMethodError => e e. << " (`#{method}' interpreted as decorator-function `#{meth}')" raise e end elsif simple_inplace_singularize!(meth) assignment = meth =~ /=$/ meth = meth.to_sym begin if assignment if Array === args each_with_index {|e,i| e.__send__ meth, args[i]} else each {|e| e.__send__ meth, args} end else map {|e| e.__send__ meth, *args, &block} end rescue NoMethodError => e e. << " (`#{method}' interpreted as map-function `#{meth}')" raise e end else throw_no method end end end # class_eval end |
.method_defined?(method, *private) ⇒ Boolean
132 133 134 135 136 137 138 139 |
# File 'lib/rmtools/enumerable/array_iterators.rb', line 132 def method_defined?(method, *private) if object_method_defined?(method, *private) true else method_str = method.to_s !!method_str.match(@@iterators_pattern) or !!simple_inplace_singularize!(method_str) end end |
.object_method_defined? ⇒ Object
def fallback_to_clean_iterators!
131 |
# File 'lib/rmtools/enumerable/array_iterators.rb', line 131 alias object_method_defined? method_defined? |
.rand(len) ⇒ Object
16 17 18 |
# File 'lib/rmtools/rand/array.rb', line 16 def self.rand(len) RMTools.randarr(len) end |
.simple_inplace_singularize!(noun) ⇒ Object
It’s here just because it’s simplier and faster (40 times) than ActiveSupport’s singularization. If you want to use latter one, run Array.use_active_support_singularize!
34 35 36 37 38 |
# File 'lib/rmtools/enumerable/array_iterators.rb', line 34 def simple_inplace_singularize!(noun) noun.sub!(/(ss|[sc]h|[xo])es([=!?]?)$/, '\1\2') or noun.sub!(/ies([=!?]?)$/, 'y\1') or noun.sub!(/s([=!?]?)$/, '\1') end |
.use_active_support_singularize! ⇒ Object
46 47 48 49 50 51 52 |
# File 'lib/rmtools/enumerable/array_iterators.rb', line 46 def use_active_support_singularize! class_eval do def simple_inplace_singularize!(noun) ActiveSupport::Inflector.singularize noun end end end |
Instance Method Details
#===(obj) ⇒ Object
making multiple pattern matching possible: a, b = ‘3’, ‘10’ case [a, b]
when [Integer, Integer]; a+b
when [/\d/, '10']; '%*d'%[a, b]
...
end
symbol :~ stands for Object
196 197 198 199 200 |
# File 'lib/rmtools/enumerable/array.rb', line 196 def ===(obj) return true if casecmp(obj) !!(obj.kinda(Array) and obj.size == size and each_with_index {|e, i| e == :~ or e === obj[i] or return false}) end |
#>>(ary) ⇒ Object
concatenation
analogy of String#>>
180 181 182 |
# File 'lib/rmtools/enumerable/array.rb', line 180 def >>(ary) ary.replace(self + ary) end |
#arrange(*args) ⇒ Object
Make hash with unique items of self
or (when block given) unique results of items yield for keys and count of them in self
, or (with option :fill) arrays of yield results, or (with option :indexes) arrays of indexes of them, or (with option :group) arrays of themselves for values
[1, 2, 2, 2, 3, 3].arrange
> 2=>3, 3=>2
[1, 2, 2, 2, 3, 3].arrange {|i| i%2}
> 1=>3
[1, 2, 2, 2, 3, 3].arrange :fill
> , 2=>[2, 2, 2], 3=>[3, 3]
[1, 2, 2, 2, 3, 3].arrange :indexes
> , 2=>[1, 2, 3], 3=>[4, 5]
[1, 2, 2, 2, 3, 3].arrange(:indexes) {|i| i%2}
> 2, 3], 1=>[0, 4, 5]
:group is analogue to rails’ group_by but twice faster [1, 2, 2, 2, 3, 3].arrange(:group) {|i| i%2}
> 2, 2], 1=>[1, 3, 3]
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 |
# File 'ext/rmtools.cpp', line 261
static VALUE rb_ary_count_items(int argc, VALUE *argv, VALUE ary)
{
long i, alen, block_given;
int fill, ind, group;
VALUE key, arg, storage;
VALUE hash = rb_hash_new();
VALUE val = Qnil;
block_given = rb_block_given_p();
rb_scan_args(argc, argv, "01", &arg);
ind = arg == ID2SYM(rb_intern("indexes"));
group = arg == ID2SYM(rb_intern("group"));
fill = ind || group || arg == ID2SYM(rb_intern("fill"));
alen = RARRAY_LEN(ary);
for (i=0; i<RARRAY_LEN(ary); i++) {
key = block_given ? rb_yield(RARRAY_PTR(ary)[i]) : RARRAY_PTR(ary)[i];
if (fill)
{
if (st_lookup(RHASH_TBL(hash), key, 0))
storage = rb_hash_aref(hash, key);
else {
storage = rb_ary_new2(alen);
rb_hash_aset(hash, key, storage);
}
rb_ary_push(storage, ind ? LONG2FIX(i) : group ? RARRAY_PTR(ary)[i] : key);
}
else {
if (st_lookup(RHASH_TBL(hash), key, &val))
rb_hash_aset(hash, key, LONG2FIX(FIX2LONG(val) + 1));
else
rb_hash_aset(hash, key, INT2FIX(1));
}
}
return hash;
}
|
#arrange_by(*args, &block) ⇒ Object
C-function, see it in /ext
156 157 158 |
# File 'lib/rmtools/enumerable/array.rb', line 156 def arrange_by(*args, &block) arrange(*args, &block) end |
#as_box(opts = {}) ⇒ Object
draw array as box just calls #inspect if max element.inspect size is greater than console width
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/rmtools/dev/present.rb', line 25 def as_box(opts={}) opts = {:max_cols => Inf, :padding => 0}.merge opts return inspect unless cols = ENV['COLUMNS'] cols = cols.to_i cell_size = map {|e| e.inspect.csize}.max + opts[:padding]*2 if n = [(1..cols/2).max {|i| i*(cell_size+1) < cols}, opts[:max_cols]].min table = div(n) border = '+'+('-'*cell_size+'+')*n need_lb = border.size < cols border << "\n" if need_lb last_border = table.last.size == n ? border : '+'+('-'*cell_size+'+')*table.last.size + '-'*((cell_size+1)*(n-table.last.size)-1) + '+' table.map {|rows| str = '|'+rows.map {|cell| cell.inspect.ccenter(cell_size)}*'|'+'|' str << ' '*((cell_size+1)*(n-rows.size)-1)+'|' if rows.size < n border + str + ("\n" if need_lb) }.join + last_border else inspect end end |
#avg ⇒ Object
arithmetics
10 11 12 |
# File 'lib/rmtools/enumerable/array.rb', line 10 def avg empty? ? nil : sum.to_f/size end |
#avg_by(&block) ⇒ Object
for use with iterators
15 16 17 |
# File 'lib/rmtools/enumerable/array.rb', line 15 def avg_by(&block) empty? ? nil : sum(&block).to_f/size end |
#casecmp ⇒ Object
186 |
# File 'lib/rmtools/enumerable/array.rb', line 186 alias :casecmp :=== |
#del_all_where(&block) ⇒ Object
59 60 61 |
# File 'lib/rmtools/enumerable/array.rb', line 59 def del_all_where(&block) reject!(&block) end |
#del_where(&block) ⇒ Object
54 55 56 57 |
# File 'lib/rmtools/enumerable/array.rb', line 54 def del_where(&block) each_with_index {|e, i| return delete_at i if block[e]} nil end |
#div(int, to_int_parts = nil) ⇒ Object
splitters
66 67 68 69 70 71 72 73 74 75 |
# File 'lib/rmtools/enumerable/array.rb', line 66 def div(int, to_int_parts=nil) len = int.to_i return [self] if len <= 0 arr = dup newarr = [] while arr.size > 0 newarr << arr.slice!(0, len) end newarr end |
#div!(int, to_int_parts = nil) ⇒ Object
77 78 79 |
# File 'lib/rmtools/enumerable/array.rb', line 77 def div!(int, to_int_parts=nil) replace(div(int, to_int_parts)) end |
#each_two ⇒ Object
yield every unique combination of two elements
210 211 212 213 214 215 216 217 |
# File 'lib/rmtools/enumerable/array.rb', line 210 def each_two _end = size-1 self[0..-2].each_with_index {|u, i| (i+1.._end).each {|j| yield u, self[j] } } end |
#evens ⇒ Object
87 88 89 |
# File 'lib/rmtools/enumerable/array.rb', line 87 def evens values_at(*(0...size).evens) end |
#every? ⇒ Boolean
conditional
92 93 94 |
# File 'lib/rmtools/enumerable/array.rb', line 92 def every? !find {|e| !yield(e)} end |
#fetch_opts(defaults = [], opts = {}) ⇒ Object Also known as: get_opts
a, b, opts = [<hash1>].fetch_opts([<hash2>, <object1>]) may work unintuitive: you’ll get <hash1> as ‘a’ and not as ‘opts’ So if function is not implying that some argument other than ‘opts’ definetly must be a hash, don’t make hash default. Better put hashie argument into opts like b, opts = [<hash1>].fetch(, :a => <hash2>) and get ‘a’ from ‘’opts’ hash
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/rmtools/core/arguments.rb', line 11 def fetch_opts(defaults=[], opts={}) if Hash === defaults opts, defaults = defaults, [] return_hash = true $log.warn "fetch_opts(<hash>) now changed, if you want to jsut fetch hash options, use `opts = <hash>.merge(opts||{})' construction", :caller => 2 else return_hash = false end opts &&= if Hash === self[-1] and !(Hash === defaults[size-1]) opts.merge pop else opts.dup end return opts if return_hash if defaults == :flags defaults = [:flags] end if defaults.last == :flags defaults.pop flags = defaults.size..-1 if defaults.size < size self[flags].each {|flag| opts[flag] = true} self[flags] = [] end end each_index {|i| import(defaults, i) if :def == self[i]} defaults.slice! 0, size concat defaults << opts end |
#find_by(key, value) ⇒ Object
find-by-value filters It’s more of a pattern. Use of respective meta-iterators is prefered.
108 109 110 |
# File 'lib/rmtools/enumerable/array.rb', line 108 def find_by(key, value) find {|e| e.__send__(key) == value} end |
#group_by(&b) ⇒ Object
fastering activesupport’s method
228 229 230 |
# File 'lib/rmtools/enumerable/array.rb', line 228 def group_by(&b) arrange(:group, &b) end |
#index_where(&block) ⇒ Object Also known as: pos
42 43 44 45 |
# File 'lib/rmtools/enumerable/array.rb', line 42 def index_where(&block) each_with_index {|e, i| return i if block[e]} nil end |
#indices_map ⇒ Object Also known as: addresses
160 161 162 163 164 |
# File 'lib/rmtools/enumerable/array.rb', line 160 def indices_map addresses = {} (size-1).downto(0) {|i| addresses[self[i]] = i} addresses end |
#indices_where(&block) ⇒ Object
48 49 50 51 52 |
# File 'lib/rmtools/enumerable/array.rb', line 48 def indices_where(&block) a = [] each_with_index {|e, i| a << i if block[e]} a end |
#map_with_index(&block) ⇒ Object
enumerating
205 206 207 |
# File 'lib/rmtools/enumerable/array.rb', line 205 def map_with_index(&block) each_with_index.map(&block) end |
#no? ⇒ Boolean
96 97 98 |
# File 'lib/rmtools/enumerable/array.rb', line 96 def no? !find {|e| yield(e)} end |
#odds ⇒ Object
filters
83 84 85 |
# File 'lib/rmtools/enumerable/array.rb', line 83 def odds values_at(*(0...size).odds) end |
#partition {|obj| ... } ⇒ Array
Same as Enumerable#partition, but twice faster
[5, 6, 1, 2, 4, 3].partition {|i| (i&1).zero?} #=> [[2, 4, 6], [1, 3, 5]]
308 309 310 311 312 313 314 315 316 317 318 319 320 321 |
# File 'ext/rmtools.cpp', line 308
static VALUE rb_ary_partition(VALUE ary)
{
VALUE select, reject;
long i, len;
RETURN_ENUMERATOR(ary, 0, 0);
len = RARRAY_LEN(ary);
select = rb_ary_new2(len);
reject = rb_ary_new2(len);
for (i = 0; i < len; i++)
rb_ary_push((RTEST(rb_yield(RARRAY_PTR(ary)[i])) ? select : reject), RARRAY_PTR(ary)[i]);
return rb_assoc_new(select, reject);
}
|
#partition_by(key, value) ⇒ Object
126 127 128 |
# File 'lib/rmtools/enumerable/array.rb', line 126 def partition_by(key, value) partition {|e| e.__send__(key) == value} end |
#present(inspect_string = nil) ⇒ Object
13 14 15 16 17 18 19 20 21 |
# File 'lib/rmtools/dev/present.rb', line 13 def present(inspect_string=nil) res = "[ " indent = (size-1).to_s.size res << map_with_index {|k,i| "#{RMTools::Painter.w(i.to_s.rjust(indent))}: #{(k.is String and !inspect_string) ? k : k.inspect}" }*"\n " res << "]" puts res end |
#rand ⇒ Object
20 21 22 |
# File 'lib/rmtools/rand/array.rb', line 20 def rand self[Kernel.rand(size)] end |
#rand! ⇒ Object
24 25 26 |
# File 'lib/rmtools/rand/array.rb', line 24 def rand! delete_at Kernel.rand size end |
#rand_by ⇒ Object
28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/rmtools/rand/array.rb', line 28 def rand_by return if empty? set, ua = Set.new, uniq s = ua.size loop { i = Kernel.rand size if set.include? i return if set.size == s elsif yield(e = ua[i]) return e else set << i end } end |
#randdiv(int) ⇒ Object
43 44 45 |
# File 'lib/rmtools/rand/array.rb', line 43 def randdiv(int) dup.randdiv!(int) end |
#randdiv!(int) ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/rmtools/rand/array.rb', line 47 def randdiv!(int) len = 2*int.to_i+1 return [self] if len <= 1 newarr = [] while size > 0 lenn = Kernel.rand(len) next if lenn < 1 newarr << slice!(0, lenn) end newarr end |
#reject_by(key, value) ⇒ Object
122 123 124 |
# File 'lib/rmtools/enumerable/array.rb', line 122 def reject_by(key, value) reject {|e| e.__send__(key) == value} end |
#rfind ⇒ Object
rightmost #find
101 102 103 104 |
# File 'lib/rmtools/enumerable/array.rb', line 101 def rfind reverse_each {|e| return e if yield e} nil end |
#rfind_by(key, value) ⇒ Object
rightmost #find_by
113 114 115 116 |
# File 'lib/rmtools/enumerable/array.rb', line 113 def rfind_by(key, value) reverse_each {|e| return e if e.__send__(key) == value} nil end |
#runiq ⇒ Object
rightmost #uniq
141 142 143 |
# File 'lib/rmtools/enumerable/array.rb', line 141 def runiq reverse.uniq.reverse end |
#runiq_by(&block) ⇒ Object
rightmost #uniq_by
146 147 148 |
# File 'lib/rmtools/enumerable/array.rb', line 146 def runiq_by(&block) reverse.uniq_by(&block).reverse end |
#scale(top) ⇒ Object
19 20 21 22 23 24 25 26 |
# File 'lib/rmtools/enumerable/array.rb', line 19 def scale(top) case top when Numeric; ratio = max.to_f/top when Array; ratio = zip(top).map {|a,b| b ? a.to_f/b : 0}.max else raise TypeError, "number or array of numbers expected, #{top.class} given" end map {|e| e/ratio} end |
#select_by(key, value) ⇒ Object
118 119 120 |
# File 'lib/rmtools/enumerable/array.rb', line 118 def select_by(key, value) select {|e| e.__send__(key) == value} end |
#set_all_where(value, &block) ⇒ Object
35 36 37 38 39 40 |
# File 'lib/rmtools/enumerable/array.rb', line 35 def set_all_where(value, &block) #select(&block).each {|e| self[index(e)] = value} # 3.643 #each_with_index {|e, i| self[i] = value if block[e]} # 0.240 # велосипедист, бля map! {|e| block[e] ? value : e} # 0.168 end |
#set_where(value, &block) ⇒ Object
setters/getters/deleters
30 31 32 33 |
# File 'lib/rmtools/enumerable/array.rb', line 30 def set_where(value, &block) each_with_index {|e, i| return self[i] = value if block[e]} nil end |
#sort_along_by(ary) ⇒ Object Also known as: order_by
167 168 169 170 171 172 173 174 175 |
# File 'lib/rmtools/enumerable/array.rb', line 167 def sort_along_by(ary) # Condition is relevant for ruby 1.9, I haven't tested it on 1.8 yet if size*ary.size > 400 addresses = ary.indices_map sort_by {|e| addresses[yield(e)]} else sort_by {|e| ary.index yield e} end end |
#sorted_uniq_by(&block) ⇒ Object
sort / group
151 152 153 |
# File 'lib/rmtools/enumerable/array.rb', line 151 def sorted_uniq_by(&block) uniq_by(&block).sort_by(&block) end |
#stranspose ⇒ Object
puts [‘123’, ‘456’, ‘789’].stranspose 147 258 369
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'ext/rmtools.cpp', line 44
static VALUE rb_ary_string_transpose(VALUE ary)
{
long elen = -1, alen, i, j;
VALUE tmp, result = 0;
alen = RARRAY_LEN(ary);
if (alen == 0) return rb_ary_dup(ary);
for (i=0; i<alen; i++) {
tmp = RARRAY_PTR(ary)[i];
if (elen < 0) { /* first element */
elen = RSTRING_LEN(tmp);
result = rb_ary_new2(elen);
for (j=0; j<elen; j++) rb_ary_store(result, j, rb_str_new("", 0));
}
else if (elen != RSTRING_LEN(tmp))
rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
RARRAY_LEN(tmp), elen);
for (j=0; j<elen; j++) rb_str_buf_cat(RARRAY_PTR(result)[j], &(RSTRING_PTR(tmp)[j]), 1);
}
return result;
}
|
#sum(identity = 0, &b) ⇒ Object
mapreduce
222 223 224 |
# File 'lib/rmtools/enumerable/array.rb', line 222 def sum(identity=0, &b) foldl(:+, &b) || identity end |
#throw_no ⇒ Object
14 |
# File 'lib/rmtools/enumerable/array_iterators.rb', line 14 alias :throw_no :method_missing |
#turn_ccw ⇒ Object
puts [‘123’, ‘456’, ‘789’].turn_ccw 369 258 147
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 |
# File 'ext/rmtools.cpp', line 72
static VALUE rb_ary_turn_ccw(VALUE ary)
{
long elen, alen, i, j;
VALUE tmp, result = 0;
alen = RARRAY_LEN(ary);
if (alen == 0) return rb_ary_dup(ary);
tmp = RARRAY_PTR(ary)[0];
if (TYPE(tmp) == T_STRING) {
elen = RSTRING_LEN(tmp);
result = rb_ary_new2(elen);
for (j=0; j<elen; j++) rb_ary_store(result, j, rb_str_new("", 0));
for (i=0; i<alen; i++) {
if (i) tmp = RARRAY_PTR(ary)[i];
if (elen != RSTRING_LEN(tmp))
rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
RARRAY_LEN(tmp), elen);
for (j=0; j<elen; j++) rb_str_buf_cat(RARRAY_PTR(result)[j], &(RSTRING_PTR(tmp)[elen-1-j]), 1);
}
}
else {
elen = RARRAY_LEN(tmp);
for (j=0; j<elen; j++) rb_ary_store(result, j, rb_ary_new2(alen));
for (i=0; i<alen; i++) {
if (i) tmp = RARRAY_PTR(ary)[i];
if (elen != RARRAY_LEN(tmp))
rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
RARRAY_LEN(tmp), elen);
for (j=0; j<elen; j++) rb_ary_store(RARRAY_PTR(result)[j], i, RARRAY_PTR(tmp)[elen-1-j]);
}
}
return result;
}
|
#turn_cw ⇒ Object
puts [‘123’, ‘456’, ‘789’].turn_cw 147 258 369
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'ext/rmtools.cpp', line 113
static VALUE rb_ary_turn_cw(VALUE ary)
{
long elen, alen, i, j;
VALUE tmp, result = 0;
alen = RARRAY_LEN(ary);
if (alen == 0) return rb_ary_dup(ary);
tmp = RARRAY_PTR(ary)[0];
if (TYPE(tmp) == T_STRING) {
elen = RSTRING_LEN(tmp);
result = rb_ary_new2(elen);
for (j=0; j<elen; j++) rb_ary_store(result, j, rb_str_new("", 0));
for (i=alen-1; i>-1; i--) {
tmp = RARRAY_PTR(ary)[i];
if (elen != RSTRING_LEN(tmp))
rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
RARRAY_LEN(tmp), elen);
for (j=0; j<elen; j++) rb_str_buf_cat(RARRAY_PTR(result)[j], &(RSTRING_PTR(tmp)[j]), 1);
}
}
else {
elen = RARRAY_LEN(tmp);
for (j=0; j<elen; j++) rb_ary_store(result, j, rb_ary_new2(alen));
for (i=0; i<alen; i++) {
if (i) tmp = RARRAY_PTR(ary)[i];
if (elen != RARRAY_LEN(tmp))
rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
RARRAY_LEN(tmp), elen);
for (j=0; j<elen; j++) rb_ary_store(RARRAY_PTR(result)[j], elen-1-i, RARRAY_PTR(tmp)[j]);
}
}
return result;
}
|
#uniq? ⇒ Boolean
uniqs
136 137 138 |
# File 'lib/rmtools/enumerable/array.rb', line 136 def uniq? uniq == self end |