Skip to content

Commit

Permalink
Merge pull request #67 from lpichler/extract_stable_sort_by
Browse files Browse the repository at this point in the history
Extract method stable_sort_by
  • Loading branch information
bdunne authored Feb 4, 2019
2 parents 572990c + 87d145b commit 9c6db74
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/more_core_extensions/all.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
require 'more_core_extensions/core_ext/array'
require 'more_core_extensions/core_ext/benchmark'
require 'more_core_extensions/core_ext/class'
require 'more_core_extensions/core_ext/enumerable'
require 'more_core_extensions/core_ext/hash'
require 'more_core_extensions/core_ext/math'
require 'more_core_extensions/core_ext/module'
Expand Down
1 change: 1 addition & 0 deletions lib/more_core_extensions/core_ext/enumerable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require 'more_core_extensions/core_ext/enumerable/sorting'
39 changes: 39 additions & 0 deletions lib/more_core_extensions/core_ext/enumerable/sorting.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
module MoreCoreExtensions
module StableSorting
def self.included(klass)
klass.class_eval do
def stable_sort_by(col_names = nil, order = nil, &block)
# stabilizer is needed because of
# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/170565
stabilizer = 0
nil_rows, sortable =
partition do |r|
Array(col_names).any? { |c| r[c].nil? }
end

data_array =
if col_names
sortable.sort_by do |r|
stabilizer += 1
[Array(col_names).map do |col|
val = r[col]
val = val.downcase if val.kind_of?(String)
val = val.to_s if val.kind_of?(FalseClass) || val.kind_of?(TrueClass)
val
end, stabilizer]
end
else
sortable.sort_by(&block)
end.to_a

data_array += nil_rows

data_array.reverse! if order == :descending
data_array
end
end
end
end
end

Enumerable.send(:include, MoreCoreExtensions::StableSorting)
65 changes: 65 additions & 0 deletions spec/core_ext/enumerable/sorting_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
describe Enumerator do
let(:unsorted_enumerable) do
[
{:id => :a, :int => 3, :string => "a", :bool => true},
{:id => :b, :int => 1, :string => "b", :bool => true},
{:id => :c, :int => 2, :string => "B", :bool => false},
{:id => :d, :int => 0, :string => "b", :bool => false},
{:id => :e, :int => 1, :string => "D", :bool => false},
{:id => :f, :int => 0, :string => "d", :bool => nil},
{:id => :g, :int => 1, :string => "E", :bool => true},
{:id => :h, :int => 2, :string => "e", :bool => true},
].to_enum
end

let(:int_sorted_array) do
[
{:id => :d, :int => 0, :string => "b", :bool => false},
{:id => :f, :int => 0, :string => "d", :bool => nil},
{:id => :b, :int => 1, :string => "b", :bool => true},
{:id => :e, :int => 1, :string => "D", :bool => false},
{:id => :g, :int => 1, :string => "E", :bool => true},
{:id => :c, :int => 2, :string => "B", :bool => false},
{:id => :h, :int => 2, :string => "e", :bool => true},
{:id => :a, :int => 3, :string => "a", :bool => true},
]
end

let(:string_sorted_array) do
[
{:id => :a, :int => 3, :string => "a", :bool => true},
{:id => :b, :int => 1, :string => "b", :bool => true},
{:id => :c, :int => 2, :string => "B", :bool => false},
{:id => :d, :int => 0, :string => "b", :bool => false},
{:id => :e, :int => 1, :string => "D", :bool => false},
{:id => :f, :int => 0, :string => "d", :bool => nil},
{:id => :g, :int => 1, :string => "E", :bool => true},
{:id => :h, :int => 2, :string => "e", :bool => true},
]
end

let(:bool_sorted_array) do
[
{:id => :c, :int => 2, :string => "B", :bool => false},
{:id => :d, :int => 0, :string => "b", :bool => false},
{:id => :e, :int => 1, :string => "D", :bool => false},
{:id => :a, :int => 3, :string => "a", :bool => true},
{:id => :b, :int => 1, :string => "b", :bool => true},
{:id => :g, :int => 1, :string => "E", :bool => true},
{:id => :h, :int => 2, :string => "e", :bool => true},
{:id => :f, :int => 0, :string => "d", :bool => nil},
]
end

it "sorts stable when order is ascending" do
expect(unsorted_enumerable.stable_sort_by([:int])).to eq(int_sorted_array)
expect(unsorted_enumerable.stable_sort_by([:string])).to eq(string_sorted_array)
expect(unsorted_enumerable.stable_sort_by([:bool])).to eq(bool_sorted_array)
end

it "sorts stable when order is descending" do
expect(unsorted_enumerable.stable_sort_by([:int], :descending)).to eq(int_sorted_array.reverse)
expect(unsorted_enumerable.stable_sort_by([:string], :descending)).to eq(string_sorted_array.reverse)
expect(unsorted_enumerable.stable_sort_by([:bool], :descending)).to eq(bool_sorted_array.reverse)
end
end

0 comments on commit 9c6db74

Please # to comment.