closest_neighbours 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6c924621de30b545235ce5ee7eaf16f3a22f642355d61284b4a5a3550e195075
4
- data.tar.gz: a4511b796aa75101d38059eb960f610ce06ab87d22625dab7af2ea805f81ec5f
3
+ metadata.gz: 1dc9ec134c754981b57d69366f513ec4768678472b18d5cf79c61513bd625b12
4
+ data.tar.gz: 27c1a7596b2708fab789d7e695d39455d104b7de76f00e0271bd6c3a4d3dec46
5
5
  SHA512:
6
- metadata.gz: 1586442b671d00ff96f54bdce79419eebd21b29ab760524ea98454483cf191265e374c7a263351f37d22dd846ee0f78077432ac58c14f00c8d9c518e9dabbf42
7
- data.tar.gz: e828070ebd738c968ad971d29680b689993796e5c690b1b764648a6a9e990b504ce6a65b981b89c97a8c8f08cd7adddb641bd384efbc78936ed935ca9d3ba76e
6
+ metadata.gz: c01f230fb3bc47584b249804c216d55bb16a2cff8dceecb187dd6a82d0bb7d860a6032a08c278f0a5ecaf1910100a36c3e7df5a3dc849d0bd2a34a29b5fd1b7b
7
+ data.tar.gz: 2bf2f4574fc4b2f0db9fbd36a7485bc790418b3e9b67c87570f827694ce5e0ab5fb9cf87343c663b6ddc8866abaf13fea9e16b6768c501531e368e63c2f54fef
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- closest_neighbours (0.1.0)
4
+ closest_neighbours (0.2.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # ClosestNeighbours
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/closest_neighbours.svg)](https://badge.fury.io/rb/closest_neighbours)
4
+ [![Build Status](https://app.travis-ci.com/aussiDavid/closest_neighbours.svg?branch=main)](https://app.travis-ci.com/aussiDavid/closest_neighbours)
5
+
3
6
  This gem takes an array of elements, groups them by their ordered closest neighbors into `n` groups.
4
7
 
5
8
  **Origin Story:**
@@ -69,11 +72,17 @@ require 'closest_neighbours'
69
72
  Use the module:
70
73
 
71
74
  ```ruby
72
- ClosestNeighbours.group(2, [1, 2, 3, 4])
75
+ ClosestNeighbours.group(2, [1, 4, 3, 2])
73
76
  # => [[1, 2], [3, 4]]
74
- ClosestNeighbours.group(3, [10.days.ago, 9.days.ago, 1.day.ago])
77
+ ClosestNeighbours.group(2, [10.days.ago, 9.days.ago, 1.day.ago])
75
78
  # => [[10.days.ago, 9.days.ago], [1.day.ago]]
79
+ ```
80
+
81
+ `ClosestNeighbours.ordered_group` allows you to squeeze additional performance out of the module by providing an ordered set of inputs. If in doubt, use `ClosestNeighbours.group`.
76
82
 
83
+ ```ruby
84
+ ClosestNeighbours.ordered_group(2, [1, 2, 3, 4])
85
+ # => [[1, 2], [3, 4]]
77
86
  ```
78
87
 
79
88
  ## Development
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ClosestNeighbours
4
+ # Error when an 1 or more element in an enumerable are not comparable with each other
5
+ class IncomparableElementError < StandardError
6
+ end
7
+ end
@@ -1,35 +1,38 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ClosestNeighbours
4
- # Match array of times up into groups that are the closest to each other
5
- class Ordered
6
- def initialize(groups = 1, data = [])
4
+ # Split an Enumerable into specified number of groups containing the closest elements in each group.
5
+ class Grouper
6
+ def initialize(orderer: DefaultOrder.new)
7
+ @orderer = orderer
8
+ end
9
+
10
+ def call(groups = 1, data = [])
7
11
  @groups = groups
8
12
  @data = data
9
- end
10
13
 
11
- def call
12
14
  validate!
13
15
 
14
16
  if groups >= size
15
17
  wraped_data + blanks
16
18
  else
17
- ranges.map { |range| sorted_data[range] }
19
+ ranges.map { |range| ordered_data[range] }
18
20
  end
19
21
  end
20
22
 
21
23
  private
22
24
 
23
- attr_reader :groups, :data
25
+ attr_reader :groups, :data, :orderer
24
26
 
25
27
  def validate!
26
28
  raise NonIntegerGroupsError unless groups.is_a? Integer
27
29
  raise NonEnumberableArgumentError unless data.is_a? Enumerable
28
30
  raise InsufficientGroupsError if groups < 1
31
+ raise IncomparableElementError unless comparable_elements?
29
32
  end
30
33
 
31
34
  def size
32
- data.to_a.size
35
+ data.count
33
36
  end
34
37
 
35
38
  def blanks
@@ -41,7 +44,7 @@ module ClosestNeighbours
41
44
  end
42
45
 
43
46
  def wraped_data
44
- sorted_data.map { |x| [x] }
47
+ ordered_data.map { |x| [x] }
45
48
  end
46
49
 
47
50
  def ranges
@@ -59,7 +62,7 @@ module ClosestNeighbours
59
62
  end
60
63
 
61
64
  def differences_between_each_pair
62
- sorted_data.each_cons(2).map { |(a, b)| b - a }
65
+ ordered_data.each_cons(2).map { |(a, b)| b - a }
63
66
  end
64
67
 
65
68
  def differences_with_indices
@@ -69,8 +72,12 @@ module ClosestNeighbours
69
72
  .reverse
70
73
  end
71
74
 
72
- def sorted_data
73
- @sorted_data ||= data.sort
75
+ def ordered_data
76
+ @ordered_data ||= orderer.call(data)
77
+ end
78
+
79
+ def comparable_elements?
80
+ data.all? { |e| data.first <=> e }
74
81
  end
75
82
  end
76
83
  end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ClosestNeighbours
4
+ # The default order of enumberales
5
+ class DefaultOrder
6
+ def call(data = [])
7
+ data.to_a
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ClosestNeighbours
4
+ # Sort an enumerator
5
+ class SortedOrder
6
+ def call(data = [])
7
+ data.sort
8
+ end
9
+ end
10
+ end
@@ -1,3 +1,3 @@
1
1
  module ClosestNeighbours
2
- VERSION = '0.1.0'.freeze
2
+ VERSION = '0.2.0'.freeze
3
3
  end
@@ -1,17 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'closest_neighbours/version'
4
- require 'closest_neighbours/ordered'
4
+ require 'closest_neighbours/grouper'
5
+
6
+ # Plugable Roles
7
+ require 'closest_neighbours/orderers/sorted_order'
8
+ require 'closest_neighbours/orderers/default_order'
5
9
 
6
10
  # Errors
7
11
  require 'closest_neighbours/errors/non_enumberable_argument_error'
8
12
  require 'closest_neighbours/errors/insufficient_groups_error'
9
13
  require 'closest_neighbours/errors/non_integer_groups_error'
14
+ require 'closest_neighbours/errors/incomparable_element_error'
10
15
 
11
- # Takes an array of elements, groups them by their ordered closest neighbors into n groups
16
+ # Top level model for Closest Neighbours gem
12
17
  module ClosestNeighbours
13
18
  #
14
- # Split an Enumerable into specified number of groups containing the closest elements in each group.
19
+ # Split an Enumerable into specified number of groups containing the closest elements in each group using the most general purpose algorithm.
15
20
  #
16
21
  # @example
17
22
  #
@@ -19,11 +24,28 @@ module ClosestNeighbours
19
24
  # # => [[2, 5], [10, 11]]
20
25
  #
21
26
  # @param [Integer] groups The number of groups to create
22
- # @param [Array|Set|Enumerable] data The data set of items to group
27
+ # @param [Enumerable] data The data set of items to group
23
28
  #
24
29
  # @return [Array] An array of `groups` groups
25
30
  #
26
31
  def self.group(groups, data)
27
- Ordered.new(groups, data).call
32
+ Grouper.new(orderer: SortedOrder.new).call(groups, data)
33
+ end
34
+
35
+ #
36
+ # Split a sorted Enumerable into specified number of groups containing the closest elements in each group.
37
+ #
38
+ # @example
39
+ #
40
+ # ClosestNeighbours.ordered_group(2, [2, 5, 10, 11])
41
+ # # => [[2, 5], [10, 11]]
42
+ #
43
+ # @param [Integer] groups The number of groups to create
44
+ # @param [Enumerable] ordered_data The data set of items to group
45
+ #
46
+ # @return [Array] An array of `groups` groups
47
+ #
48
+ def self.ordered_group(groups, ordered_data)
49
+ Grouper.new(orderer: DefaultOrder.new).call(groups, ordered_data)
28
50
  end
29
51
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: closest_neighbours
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Milanese
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-09-15 00:00:00.000000000 Z
11
+ date: 2021-09-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -132,10 +132,13 @@ files:
132
132
  - bin/setup
133
133
  - closest_neighbours.gemspec
134
134
  - lib/closest_neighbours.rb
135
+ - lib/closest_neighbours/errors/incomparable_element_error.rb
135
136
  - lib/closest_neighbours/errors/insufficient_groups_error.rb
136
137
  - lib/closest_neighbours/errors/non_enumberable_argument_error.rb
137
138
  - lib/closest_neighbours/errors/non_integer_groups_error.rb
138
- - lib/closest_neighbours/ordered.rb
139
+ - lib/closest_neighbours/grouper.rb
140
+ - lib/closest_neighbours/orderers/default_order.rb
141
+ - lib/closest_neighbours/orderers/sorted_order.rb
139
142
  - lib/closest_neighbours/version.rb
140
143
  homepage: https://github.com/aussidavid/closest_neighbours
141
144
  licenses: