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.

Examples:

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


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

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.

Examples:

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

Raises:

  • (ArgumentError)


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

def random_subarray(n = 1)
  raise ArgumentError, "negative argument" if n < 0

  (1..n).map do
    r = rand(2**size)
    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 operator or both can be supplied. This method may eventually be moved to the Enumerable module.

Examples:

Symbol argument

a = (1..4).to_a
a.reductions(:+) #=> [1, 3, 6, 10]

Initial value and symbol argument

a.reductions(50, :+) #=> [50, 51, 53, 56, 60]

Block argument

%w(a b c).reductions { |s1, s2| s1+s2 } #=> ["a", "ab", "abc"]

Raises:

  • (ArgumentError)


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

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]]) { |(acc, result), el|
    val = op ? acc.send(op, el) : yield(acc, el)
    [val, result << val]
  }.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.

Examples:

With a symbol

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

With a block

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


12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/shenanigans/array/zip_with.rb', line 12

def zip_with(other, op = nil)
  return [] if 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