class Array

Public Instance Methods

^(other) click to toggle source

Returns an array containing elements exclusive between two arrays.

@example

[1, 2, 3] ^ [1, 2, 4] #=> [3, 4]
# File lib/shenanigans/array/caret.rb, line 6
def ^(other)
  (self - other) | (other - self)
end
random_subarray(n = 1) click to toggle source

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

@example

a = *1..5
a.random_subarray(3) #=> [[1, 3, 5], [2, 4], [1, 3, 4, 5]]
# 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) { |acc, el| ... } click to toggle source

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.

@example Symbol argument

a = (1..4).to_a
a.reductions(:+) #=> 10

@example Initial value and symbol argument

a.reductions(50, :+) #=> 60

@example Block argument

%w(a b c).reductions { |s1, s2| s1+s2 } #=> ["a", "ab", "abc"]
# 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) { |a, b| ... } click to toggle source

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. @example With a symbol

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

@example With a block

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