Class: Array

Inherits:
Object show all
Defined in:
lib/shenanigans/array/caret.rb,
lib/shenanigans/array/zip_with.rb,
lib/shenanigans/array/reductions.rb,
lib/shenanigans/array/random_subarray.rb

Instance Method Summary collapse

Instance Method Details

#^(other) ⇒ Object

Returns an array containing elements exclusive between two arrays.

[1, 2, 3] ^ [1, 2, 4]
#=> [3, 4]

5
6
7
# File 'lib/shenanigans/array/caret.rb', line 5

def ^(other)
  (self - other) | (other - self)
end

#random_subarray(n = 1) ⇒ Object

Generates random subarrays. Uses random numbers and bit-fiddling to assure performant uniform distributions even for large arrays.

a = *1..5
a.random_subarray(3)
#=> [[1, 3, 5], [2, 4], [1, 3, 4, 5]]

Raises:

  • (ArgumentError)

9
10
11
12
13
14
15
# File 'lib/shenanigans/array/random_subarray.rb', line 9

def random_subarray(n=1)
  raise ArgumentError, "negative argument" if n < 0
  (1..n).map do
    r = rand(2**self.size)
    self.select.with_index { |_, i| r[i] == 1 }
  end
end

#reductions(*args, &block) ⇒ Object

Similar to reduce/inject, but also returns intermediate values. Has the same interface as reduce/inject, so an initial value, an oprator or both can be supplied. This method may eventually be moved to the Enumerable module.

a = [*1..4]
a.reductions(:+)
#=> 10
a.reductions(50, :+)
#=> 60
%w(a b c).reductions { |s1, s2| s1+s2 }
#=> ["a", "ab", "abc"]

Raises:

  • (ArgumentError)

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/shenanigans/array/reductions.rb', line 11

def reductions(*args, &block)
  arr = dup

  if args.size == 1
    Symbol === (arg = args.first) ? op = arg : initial = arg
  else
    initial, op, _ = args
  end

  raise ArgumentError, "Need an operator or block" unless op || block

  initial ||= arr.shift

  arr.inject([initial, [initial]]) do |(acc, result), el|
    val = op ? acc.send(op, el) : yield(acc, el)
    [val, result << val]
  end.last
end

#zip_with(other, op = nil) ⇒ Object

Zip self with other, combining the elements with the provided block or symbol. The resulting array will be as long as the shorter of the two arrays.

[1,2,3].zip_with([6,5,4], :+)
#=> [7, 7, 7]
%w(a b).zip_with(%w(c d), :+)
#=> ["ac", "bd"]

For more complex combinations, a block can be provided:

[1,2,3].zip_with([6,5,4]) { |a,b| 3*a+2*b }
#=> [15, 16, 17]

16
17
18
19
20
21
22
23
24
25
26
# File 'lib/shenanigans/array/zip_with.rb', line 16

def zip_with(other, op=nil)
  return [] if self.empty? || other.empty?
  clipped = self[0..other.length-1]
  zipped = clipped.zip(other)

  if op
    zipped.map { |a, b| a.send(op, b) }
  else
    zipped.map { |a, b| yield(a, b) }
  end
end