closest_neighbours 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1dc9ec134c754981b57d69366f513ec4768678472b18d5cf79c61513bd625b12
4
- data.tar.gz: 27c1a7596b2708fab789d7e695d39455d104b7de76f00e0271bd6c3a4d3dec46
3
+ metadata.gz: 576f497b27d6ebba11b54ebb51a3ec247930037fbe149ed0e2ae92bb8b073c92
4
+ data.tar.gz: b4d3540e6218de82d923eeb688819d13ece9610967bfc09bdad62dcf08804cb3
5
5
  SHA512:
6
- metadata.gz: c01f230fb3bc47584b249804c216d55bb16a2cff8dceecb187dd6a82d0bb7d860a6032a08c278f0a5ecaf1910100a36c3e7df5a3dc849d0bd2a34a29b5fd1b7b
7
- data.tar.gz: 2bf2f4574fc4b2f0db9fbd36a7485bc790418b3e9b67c87570f827694ce5e0ab5fb9cf87343c663b6ddc8866abaf13fea9e16b6768c501531e368e63c2f54fef
6
+ metadata.gz: ea2d077995597448fa9430e97c07f1f5a127a1fdc5f33cf6b08152cffa307ecde35cdf044ef0f111de07a3f0562cd8d12aa2cd7d30cd16c87ec44e1eb704e5de
7
+ data.tar.gz: bd1c0aff794d5aedcfeaa2be93970f3574e227d46e58ea0eb7fac632da15c3d11324c169724c51d0178637d08e88b9a117492404021b0bd917802a049fa50b29
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- closest_neighbours (0.2.0)
4
+ closest_neighbours (0.2.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'closest_neighbours/indexer'
4
+
3
5
  module ClosestNeighbours
4
6
  # Split an Enumerable into specified number of groups containing the closest elements in each group.
5
7
  class Grouper
@@ -8,76 +10,52 @@ module ClosestNeighbours
8
10
  end
9
11
 
10
12
  def call(groups = 1, data = [])
11
- @groups = groups
12
- @data = data
13
-
14
- validate!
15
-
16
- if groups >= size
17
- wraped_data + blanks
18
- else
19
- ranges.map { |range| ordered_data[range] }
20
- end
21
- end
22
-
23
- private
24
-
25
- attr_reader :groups, :data, :orderer
26
-
27
- def validate!
28
13
  raise NonIntegerGroupsError unless groups.is_a? Integer
29
14
  raise NonEnumberableArgumentError unless data.is_a? Enumerable
30
15
  raise InsufficientGroupsError if groups < 1
31
- raise IncomparableElementError unless comparable_elements?
32
- end
16
+ raise IncomparableElementError unless data.all? { |e| e <=> data.first }
33
17
 
34
- def size
35
- data.count
18
+ GrouperHelper.new(groups, orderer.call(data)).call
36
19
  end
37
20
 
38
- def blanks
39
- Array.new(number_of_blanks, [])
40
- end
21
+ private
41
22
 
42
- def number_of_blanks
43
- [0, groups - size].max
44
- end
23
+ attr_reader :orderer
45
24
 
46
- def wraped_data
47
- ordered_data.map { |x| [x] }
48
- end
25
+ # Helper class to index data and extract ranges from an enumberble
26
+ class GrouperHelper
27
+ def initialize(groups, data)
28
+ @groups = groups
29
+ @data = data
30
+ end
49
31
 
50
- def ranges
51
- [0..indexes[0]] +
52
- (indexes << size).each_cons(2)
53
- .map { |(left, right)| (left + 1)..right }
54
- end
32
+ def call
33
+ if groups == 1
34
+ [data]
35
+ elsif groups >= data.count
36
+ cells + blanks
37
+ else
38
+ ranges.map { |range| data[range] }
39
+ end
40
+ end
55
41
 
56
- def indexes
57
- @indexes ||= differences_with_indices
58
- .lazy
59
- .map(&:last)
60
- .first(groups - 1)
61
- .sort
62
- end
42
+ private
63
43
 
64
- def differences_between_each_pair
65
- ordered_data.each_cons(2).map { |(a, b)| b - a }
66
- end
44
+ attr_reader :groups, :data
67
45
 
68
- def differences_with_indices
69
- differences_between_each_pair
70
- .map.with_index { |x, i| [x, i] }
71
- .sort
72
- .reverse
73
- end
46
+ def cells
47
+ data.map { |x| [x] }
48
+ end
74
49
 
75
- def ordered_data
76
- @ordered_data ||= orderer.call(data)
77
- end
50
+ def blanks
51
+ Array.new([0, groups - data.count].max, [])
52
+ end
78
53
 
79
- def comparable_elements?
80
- data.all? { |e| data.first <=> e }
54
+ def ranges
55
+ Indexer.new(groups, data).call
56
+ .each_cons(2)
57
+ .map { |(left, right)| left...right }
58
+ end
81
59
  end
82
60
  end
83
61
  end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ClosestNeighbours
4
+ # Determines the indexes where the data need to be grouped
5
+ class Indexer
6
+ def initialize(groups = 1, data = [])
7
+ @groups = groups
8
+ @data = data
9
+ end
10
+
11
+ def call
12
+ [0] + indexes + [data.count]
13
+ end
14
+
15
+ private
16
+
17
+ attr_reader :groups, :data
18
+
19
+ def indexes
20
+ if same?
21
+ even
22
+ else
23
+ dynamic
24
+ end
25
+ end
26
+
27
+ def same?
28
+ differences_between_each_element.all? { |x| x == differences_between_each_element.first }
29
+ end
30
+
31
+ def even
32
+ (1...groups).map do |i|
33
+ i * (data.count / groups.to_f).ceil
34
+ end
35
+ end
36
+
37
+ def dynamic
38
+ differences_between_each_element
39
+ .with_index
40
+ .sort_by { |(diff, _)| -diff }
41
+ .first(groups - 1)
42
+ .map { |(_, i)| i + 1 }
43
+ .sort
44
+ end
45
+
46
+ def differences_between_each_element
47
+ data.lazy
48
+ .each_cons(2)
49
+ .map { |(lower, higher)| higher - lower }
50
+ end
51
+ end
52
+ end
@@ -1,3 +1,3 @@
1
1
  module ClosestNeighbours
2
- VERSION = '0.2.0'.freeze
2
+ VERSION = '0.2.1'.freeze
3
3
  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.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Milanese
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-09-17 00:00:00.000000000 Z
11
+ date: 2021-09-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -137,6 +137,7 @@ files:
137
137
  - lib/closest_neighbours/errors/non_enumberable_argument_error.rb
138
138
  - lib/closest_neighbours/errors/non_integer_groups_error.rb
139
139
  - lib/closest_neighbours/grouper.rb
140
+ - lib/closest_neighbours/indexer.rb
140
141
  - lib/closest_neighbours/orderers/default_order.rb
141
142
  - lib/closest_neighbours/orderers/sorted_order.rb
142
143
  - lib/closest_neighbours/version.rb
@@ -146,7 +147,7 @@ licenses:
146
147
  metadata:
147
148
  homepage_uri: https://github.com/aussidavid/closest_neighbours
148
149
  source_code_uri: https://github.com/aussidavid/closest_neighbours
149
- post_install_message:
150
+ post_install_message:
150
151
  rdoc_options: []
151
152
  require_paths:
152
153
  - lib
@@ -162,7 +163,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
162
163
  version: '0'
163
164
  requirements: []
164
165
  rubygems_version: 3.1.6
165
- signing_key:
166
+ signing_key:
166
167
  specification_version: 4
167
168
  summary: Takes an array of elements, groups them by their ordered closest neighbors
168
169
  into n groups