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 +4 -4
- data/Gemfile.lock +1 -1
- data/lib/closest_neighbours/grouper.rb +34 -56
- data/lib/closest_neighbours/indexer.rb +52 -0
- data/lib/closest_neighbours/version.rb +1 -1
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 576f497b27d6ebba11b54ebb51a3ec247930037fbe149ed0e2ae92bb8b073c92
|
4
|
+
data.tar.gz: b4d3540e6218de82d923eeb688819d13ece9610967bfc09bdad62dcf08804cb3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ea2d077995597448fa9430e97c07f1f5a127a1fdc5f33cf6b08152cffa307ecde35cdf044ef0f111de07a3f0562cd8d12aa2cd7d30cd16c87ec44e1eb704e5de
|
7
|
+
data.tar.gz: bd1c0aff794d5aedcfeaa2be93970f3574e227d46e58ea0eb7fac632da15c3d11324c169724c51d0178637d08e88b9a117492404021b0bd917802a049fa50b29
|
data/Gemfile.lock
CHANGED
@@ -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
|
32
|
-
end
|
16
|
+
raise IncomparableElementError unless data.all? { |e| e <=> data.first }
|
33
17
|
|
34
|
-
|
35
|
-
data.count
|
18
|
+
GrouperHelper.new(groups, orderer.call(data)).call
|
36
19
|
end
|
37
20
|
|
38
|
-
|
39
|
-
Array.new(number_of_blanks, [])
|
40
|
-
end
|
21
|
+
private
|
41
22
|
|
42
|
-
|
43
|
-
[0, groups - size].max
|
44
|
-
end
|
23
|
+
attr_reader :orderer
|
45
24
|
|
46
|
-
|
47
|
-
|
48
|
-
|
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
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
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
|
-
|
57
|
-
@indexes ||= differences_with_indices
|
58
|
-
.lazy
|
59
|
-
.map(&:last)
|
60
|
-
.first(groups - 1)
|
61
|
-
.sort
|
62
|
-
end
|
42
|
+
private
|
63
43
|
|
64
|
-
|
65
|
-
ordered_data.each_cons(2).map { |(a, b)| b - a }
|
66
|
-
end
|
44
|
+
attr_reader :groups, :data
|
67
45
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
.sort
|
72
|
-
.reverse
|
73
|
-
end
|
46
|
+
def cells
|
47
|
+
data.map { |x| [x] }
|
48
|
+
end
|
74
49
|
|
75
|
-
|
76
|
-
|
77
|
-
|
50
|
+
def blanks
|
51
|
+
Array.new([0, groups - data.count].max, [])
|
52
|
+
end
|
78
53
|
|
79
|
-
|
80
|
-
|
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
|
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.
|
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-
|
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
|