closest_neighbours 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|