closest_neighbours 0.1.0 → 0.2.0
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/README.md +11 -2
- data/lib/closest_neighbours/errors/incomparable_element_error.rb +7 -0
- data/lib/closest_neighbours/{ordered.rb → grouper.rb} +19 -12
- data/lib/closest_neighbours/orderers/default_order.rb +10 -0
- data/lib/closest_neighbours/orderers/sorted_order.rb +10 -0
- data/lib/closest_neighbours/version.rb +1 -1
- data/lib/closest_neighbours.rb +27 -5
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1dc9ec134c754981b57d69366f513ec4768678472b18d5cf79c61513bd625b12
|
4
|
+
data.tar.gz: 27c1a7596b2708fab789d7e695d39455d104b7de76f00e0271bd6c3a4d3dec46
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c01f230fb3bc47584b249804c216d55bb16a2cff8dceecb187dd6a82d0bb7d860a6032a08c278f0a5ecaf1910100a36c3e7df5a3dc849d0bd2a34a29b5fd1b7b
|
7
|
+
data.tar.gz: 2bf2f4574fc4b2f0db9fbd36a7485bc790418b3e9b67c87570f827694ce5e0ab5fb9cf87343c663b6ddc8866abaf13fea9e16b6768c501531e368e63c2f54fef
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# ClosestNeighbours
|
2
2
|
|
3
|
+
[](https://badge.fury.io/rb/closest_neighbours)
|
4
|
+
[](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,
|
75
|
+
ClosestNeighbours.group(2, [1, 4, 3, 2])
|
73
76
|
# => [[1, 2], [3, 4]]
|
74
|
-
ClosestNeighbours.group(
|
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
|
@@ -1,35 +1,38 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ClosestNeighbours
|
4
|
-
#
|
5
|
-
class
|
6
|
-
def initialize(
|
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|
|
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.
|
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
|
-
|
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
|
-
|
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
|
73
|
-
@
|
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
|
data/lib/closest_neighbours.rb
CHANGED
@@ -1,17 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'closest_neighbours/version'
|
4
|
-
require 'closest_neighbours/
|
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
|
-
#
|
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 [
|
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
|
-
|
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.
|
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-
|
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/
|
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:
|