Skip to content

Instantly share code, notes, and snippets.

@shipstar
Last active April 11, 2017 19:14
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shipstar/653710de2f1179b0e70b to your computer and use it in GitHub Desktop.
Save shipstar/653710de2f1179b0e70b to your computer and use it in GitHub Desktop.
Kyle's solutions to Winston's thing
def find_duplicates(arr)
arr \
.group_by(&:itself)
.map { |el, appearances| el if appearances.size > 1 }
.compact
end
# Walkthrough:
# 1. [1,2,2,3,3,3].group_by(&:itself)
# => { 1 => [1], 2 => [2,2], 3 => [3,3,3] }
# 2. map the key if there are multiple appearances, nil if only one appearance
# 3. compact removes any nils that were mapped in step 2
# Interesting bits:
# 1. I didn't know :itself was a method now.
# 2. Requires two passes (map and compact)
# which could be sub-optimal on large data sets
# (although compact seems pretty performant).
# To avoid the two-pass issue from above, we need something that only adds
# to the array if the value isn't nil.
# compact_map seems like a good name, and it turns out there's a proposal for it:
# https://bugs.ruby-lang.org/issues/5663
# I would only monkey patch this if:
#
# 1. I was using it in many places.
# 2. Performance isn't worse than map.compact,
# since this is in Ruby and that's probably in C.
#
# If not #1 and #2, I'd probably just leave it as-is.
module Enumerable
# Much like map, we need to allow transformations here:
# { 1 => 2, 3 => nil, 4 => 5 }.compact_map { |k,v| k * 9 if v }
# => [9, 36]
# It should also return the original enumerable if called without a block:
# { 1 => 2, 3 => nil, 4 => 5 }.compact_map
# (Currently mine returns the equivalent of hash.map.to_a
# instead of an enumerable. Should probably fix that before production.)
def compact_map
inject([]) do |memo, val|
transformed = block_given? ? yield(val) : val
memo << transformed if transformed
memo
end
end
end
def find_duplicates(arr)
arr \
.group_by(&:itself)
.compact_map { |el, appearances| el if appearances.size > 1 }
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment