Skip to content

Instantly share code, notes, and snippets.

@peterellisjones
Last active February 12, 2024 07:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save peterellisjones/4362838 to your computer and use it in GitHub Desktop.
Save peterellisjones/4362838 to your computer and use it in GitHub Desktop.
Some extensions to Ruby's Enumerable class to allow some fancy functional programming. More info here: http://ukoki.com/post/38615453403/extending-rubys-enumerable
#
# Extensions to Enumerable to add more functional operators
# More info here: http://ukoki.com/post/38615453403/extending-rubys-enumerable
#
module Enumerable
# example:
# [1,2,3].zip_map([1,2,3], [1,2,3]) { |x,y,z| x * y * z }
# => [1,8,27]
def zip_map *lists
self.map.with_index do |elem, idx|
args = [elem] + lists.each.with_object(idx).map(&:[])
yield *args, idx
end
end
# example:
# [[1,2],[3,4],[5,6]].map_at_level(2) { |n| -n }
# => [[-1, -2], [-3, -4], [-5, -6]]
def map_at_level level = 1, &block
if level <= 1
self.map &block
else
self.map { |e| e.map_at_level level-1, &block }
end
end
# example:
# [[1,2,3],['a','b','c']].transpose
# => [[1, "a"], [2, "b"], [3, "c"]]
def transpose
self.with_index do |i|
yield self.with_object(i).map &:[]
end
end
# example:
# [[[[1],[2],[3]],[['a'],['b'],['c']]]].flatten_at_level(2)
# => [[[1, 2, 3], ['a','b','c']]]
def flatten_at_level level, depth = nil
self.map_at_level(level) { |list| list.flatten depth }
end
# example:
# [1,2,3,4,5,6,7,8,9,10].group(3)
# => [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
def group size # groups list into sublists of size 'size'
self.each_slice(size).to_a
end
def blockify width, height = nil # groups 2D array into sub-2D-arrays of size widthxheight
self.each_slice(height||width).map { |n| n.transpose.group(width) }.flatten(1)
end
end
@artyomb
Copy link

artyomb commented Feb 12, 2024

I find sometimes useful

module Enumerable
  # Maybe somedays: .each(&:method, args) do; end 
  def each_call(method, *args,  &block) = each { _1.send method, *args, &block }
  def map_call(method, *args,  &block) = map { _1.send method, *args, &block }
  def map_call!(method, *args,  &block) = map! { _1.send method, *args, &block }
end
# ======
a = %w[a b c]
a.each_call(:instance_eval) do
    @var = 1
end
p a.map_call(:+, '!')

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment