Skip to content

Instantly share code, notes, and snippets.

@dimanyc
Created June 7, 2017 05:04
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 dimanyc/961fd7f89773933e57e33d5d402b0c4f to your computer and use it in GitHub Desktop.
Save dimanyc/961fd7f89773933e57e33d5d402b0c4f to your computer and use it in GitHub Desktop.
MemberUniqualizer Array Refinement
module MemberUniquelizer
refine Array do
# makes each member within an array
# unique by appending a unique number
def uniquelize(ary = self)
ary.map { |member| format_member(member) }
.flatten
.uniq
end
private
# returns pure or formated member string
# depending on present repetitions
def format_member(member)
contains_repetitions?(member) ? append_sequence(member) : member
end
# checks for repeated members
def contains_repetitions?(member)
repetitions_hash[member].count > 1
end
# returns an array of members
# with appended sequential numbes
def append_sequence(member)
repetitions_hash[member].map.with_index do |repeated_member, index|
name = repeated_member.nil? ? 'empty' : repeated_member
"#{name}_repeat#{index + 1}"
end
end
# returns a hash containg elements and
# their number of occurances within array
def repetitions_hash
group_by { |member| member }
end
end
end
#------------------------------------------------------------------------#
### MemberUniquelizer spec
require 'rails_helper'
using MemberUniquelizer
RSpec.describe MemberUniquelizer do
it 'should add a counter to repeated memebers of an Array' do
ary = ['a', 'a', 'c']
expect(ary.uniquelize)
.to eq(['a_repeat1', 'a_repeat2', 'c'])
end
it 'should count the number of repetitions' do
ary = ['a', 'a', 'c']
expect(ary.send(:repetitions_hash))
.to eq({
'a' => ['a', 'a'],
'c' => ['c']
})
end
it 'should append sequential number to repeated members' do
ary = ['a', 'a', 'c']
expect(ary.send(:append_sequence, 'a'))
.to include('a_repeat1', 'a_repeat2')
end
it 'should identify whether a memeber is repeated' do
ary = ['a', 'a', 'c']
expect(ary.send(:contains_repetitions?, 'a'))
.to be_truthy
end
it 'should identify whether a memeber is unique' do
ary = ['a', 'a', 'c']
expect(ary.send(:contains_repetitions?, 'c'))
.to be_falsey
end
it 'should format repeated members' do
ary = ['a', 'a', 'c']
expect(ary.send(:format_member, 'a'))
.to include('a_repeat1', 'a_repeat2')
end
it 'should not format unique members' do
ary = ['a', 'a', 'c']
expect(ary.send(:format_member, 'c'))
.to include('c')
end
context 'when supplied array contains empty members' do
context 'when supplied array contains a single empty member' do
let(:ary) { ['a', nil, 'a', 'c'] }
it 'should keep the empty member and proceed with the rest' do
expect(ary.uniquelize)
.to include('a_repeat1', nil, 'a_repeat2', 'c')
end
end # when single nil
context 'when supplied array contains multiple empty members' do
let(:ary) { [ nil, nil, 'a', 'a'] }
it 'should keep the empty member and proceed with the rest' do
expect(ary.uniquelize)
.to include(
'empty_repeat1',
'empty_repeat2',
'a_repeat1',
'a_repeat2')
end
end # when multiple nils
end # when include nil
context 'when supplied array contains non-string members' do
let(:ary) { [1, 1, :foo, :foo] }
it 'should turn these members intro strings' do
expect(ary.uniquelize)
.to include(
'1_repeat1',
'1_repeat2',
'foo_repeat1',
'foo_repeat2')
end
end # with non-strings
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment