Last active
November 24, 2017 21:39
-
-
Save dfurber/7547568 to your computer and use it in GitHub Desktop.
Experiments in tail recursion with Ruby, implementing group_by, index_by, in_groups_of, and sort_by without iteration or conditionals. Because why not?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
items = %w{foo bar baz goo gar gaz hoo har haz} | |
def recurse_array(ary, &block) | |
head, *tail = ary | |
head and block.call(head) | |
tail.any? and recurse_array(tail, &block) | |
end | |
puts "First the items in order:\n" | |
recurse_array items do |item| | |
puts item | |
end | |
puts "\n" | |
puts "And now in reverse order: \n" | |
recurse_array items.reverse do |item| | |
puts item | |
end | |
puts "\n" | |
puts "Now let's group them by the first letter: \n" | |
grouped = {} | |
recurse_array(items) do |item| | |
(grouped[item[0]] ||= []) << item | |
end | |
puts grouped.inspect | |
def sort_by(list, &block) | |
sl = list.clone | |
sl.size <=1 and sl or begin | |
pivot = sl.pop | |
left, right = sl.partition { |e| block.call(e) < block.call(pivot) } | |
sort_by(left, &block) + [pivot] + sort_by(right, &block) | |
end | |
end | |
def tuple_array_to_hash(ary) | |
new_hash = {} | |
recurse_array(ary) { |item| new_hash[item[0]] = item[1] } | |
new_hash | |
end | |
def ksort(grouped, &block) | |
tuple_array_to_hash sort_by(grouped.to_a, &:first) | |
end | |
def group_by(ary, &block) | |
grouped, sorted = {}, {} | |
recurse_array(ary) do |item| | |
(grouped[block.call(item)] ||= []) << item | |
end | |
ksort grouped | |
end | |
puts "\n" | |
puts "Now let's group them and key sort them:\n" | |
grouped_items = group_by(items) { |item| item[0] } | |
puts grouped_items.inspect | |
def index_by(ary, &block) | |
keyed = {} | |
recurse_array(ary) { |item| keyed[block.call(item)] = item } | |
keyed | |
end | |
puts "\n" | |
puts "Now let's index them by the MD5 hash of each item:\n" | |
require 'digest/md5' | |
indexed_items = ksort index_by(items) { |item| Digest::MD5.hexdigest item } | |
puts indexed_items.inspect | |
def head_and_tail(ary, size) | |
return ary.take(size), ary.drop(size) | |
end | |
def in_groups_of(ary, size, &block) | |
head, tail = head_and_tail ary, size | |
head and block.call(head) | |
tail.any? and in_groups_of(tail, size, &block) | |
end | |
puts "\n" | |
puts "Now in groups of 3:\n" | |
in_groups_of(items, 3) { |group| puts group.inspect } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment