ranges_merger 0.0.0 → 0.1.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.
- data/README.rdoc +37 -1
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/ranges_merger.rb +73 -6
- data/ranges_merger.gemspec +2 -2
- data/spec/ranges_merger_spec.rb +124 -6
- metadata +12 -11
data/README.rdoc
CHANGED
@@ -4,7 +4,9 @@ Very simple gem for merging range-like objects.
|
|
4
4
|
|
5
5
|
== How to use
|
6
6
|
|
7
|
-
|
7
|
+
Please use range-like object converted to format [[from, to], [from, to], ...].
|
8
|
+
|
9
|
+
If you want to merge 2 ranges please use code just like below.
|
8
10
|
|
9
11
|
a = [1, 3]
|
10
12
|
|
@@ -14,6 +16,40 @@ At this moment...
|
|
14
16
|
|
15
17
|
# => result = [[1, 4]]
|
16
18
|
|
19
|
+
|
20
|
+
|
21
|
+
If you want to merge more than 2 ranges please use code just like below.
|
22
|
+
|
23
|
+
a = [1, 3]
|
24
|
+
|
25
|
+
b = [2, 4]
|
26
|
+
|
27
|
+
c = [4, 6]
|
28
|
+
|
29
|
+
result = RangesMerger.merge([a, b, c])
|
30
|
+
|
31
|
+
# => result = [[1, 6]]
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
If you want to merge Range objects.
|
36
|
+
|
37
|
+
ranges = [
|
38
|
+
|
39
|
+
(1..2),
|
40
|
+
|
41
|
+
(2..3),
|
42
|
+
|
43
|
+
(5..8)
|
44
|
+
|
45
|
+
]
|
46
|
+
|
47
|
+
result = RangesMerger.merge(ranges)
|
48
|
+
|
49
|
+
# => result = [(1..3),(5..8)]
|
50
|
+
|
51
|
+
|
52
|
+
|
17
53
|
== Contributing to ranges_merger
|
18
54
|
|
19
55
|
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
data/Rakefile
CHANGED
@@ -18,7 +18,7 @@ Jeweler::Tasks.new do |gem|
|
|
18
18
|
gem.homepage = "http://github.com/akwiatkowski/ranges_merger"
|
19
19
|
gem.license = "LPGLv3"
|
20
20
|
gem.summary = %Q{Small gem for merging range-like objects}
|
21
|
-
gem.description = %Q{Simple gem used for merging range-like objects}
|
21
|
+
gem.description = %Q{Simple gem used for merging range-like objects. If you have problems with operations on ranges this gem can save you some time.}
|
22
22
|
gem.email = "bobikx@poczta.fm"
|
23
23
|
gem.authors = ["Aleksander Kwiatkowski"]
|
24
24
|
# dependencies defined in Gemfile
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.1.0
|
data/lib/ranges_merger.rb
CHANGED
@@ -1,31 +1,98 @@
|
|
1
1
|
class RangesMerger
|
2
|
+
|
3
|
+
# Merge for various objects (Array, Range)
|
4
|
+
def self.merge(_array)
|
5
|
+
klass = _array.first.class
|
6
|
+
|
7
|
+
if klass.to_s == "Array"
|
8
|
+
return self.merge_loop(_array)
|
9
|
+
elsif klass.to_s == "Range"
|
10
|
+
result = self.merge_loop( _array.collect{|a| [a.first, a.last]} )
|
11
|
+
return result.collect{|r| Range.new(r[0], r[1])}
|
12
|
+
else
|
13
|
+
return []
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
# Merge loop
|
19
|
+
def self.merge_loop(_array)
|
20
|
+
before = _array
|
21
|
+
while true do
|
22
|
+
after = self.merge_array(_array)
|
23
|
+
return after if before == after or not check_overlaps(after)
|
24
|
+
before = after
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.merge_array(_array)
|
29
|
+
return _array if _array.size <= 1
|
30
|
+
sorted = _array.sort { |a, b| a[0] <=> b[0] }.uniq
|
31
|
+
|
32
|
+
i = 1
|
33
|
+
while i < sorted.size do
|
34
|
+
to_merge = [sorted[i-1], sorted[i]]
|
35
|
+
# puts "merging #{to_merge.inspect}"
|
36
|
+
|
37
|
+
result = self.two_way_merge(to_merge)
|
38
|
+
# puts "merged #{result.inspect}"
|
39
|
+
|
40
|
+
sorted[i-1] = result[0]
|
41
|
+
|
42
|
+
if result.size == 1
|
43
|
+
sorted[i] = nil
|
44
|
+
sorted.delete_if { |s| s.nil? }
|
45
|
+
else
|
46
|
+
i += 1
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
return sorted
|
51
|
+
end
|
52
|
+
|
53
|
+
# Check if there are overlaps in Array
|
54
|
+
def self.check_overlaps(_array)
|
55
|
+
sorted = _array.sort { |a, b| a[0] <=> b[0] }.uniq
|
56
|
+
|
57
|
+
(1...sorted.size).each do |i|
|
58
|
+
return true if sorted[i][0] <= sorted[i-1][0]
|
59
|
+
return true if sorted[i][0] <= sorted[i-1][1]
|
60
|
+
end
|
61
|
+
return false
|
62
|
+
end
|
63
|
+
|
2
64
|
def self.two_way_merge(_array)
|
3
65
|
a_from = _array[0][0]
|
4
66
|
b_from = _array[1][0]
|
5
67
|
a_to = _array[0][1]
|
6
68
|
b_to = _array[1][1]
|
7
69
|
|
8
|
-
#
|
9
|
-
if (a_to < b_to and a_from < b_from and a_to < b_from)
|
70
|
+
# 1A. outside each other A > B
|
71
|
+
if (a_to < b_to and a_from < b_from and a_to < b_from)
|
10
72
|
return [[a_from, a_to], [b_from, b_to]]
|
11
73
|
end
|
12
74
|
|
13
|
-
#
|
75
|
+
# 1B. outside each other B > A
|
76
|
+
if (a_to > b_to and a_from > b_from and b_to < a_from)
|
77
|
+
return [[b_from, b_to], [a_from, a_to]]
|
78
|
+
end
|
79
|
+
|
80
|
+
# 2A. A is inside B
|
14
81
|
if a_from >= b_from and a_to <= b_to
|
15
82
|
return [[b_from, b_to]]
|
16
83
|
end
|
17
84
|
|
18
|
-
#
|
85
|
+
# 2B. B is inside A
|
19
86
|
if b_from >= a_from and b_to <= a_to
|
20
87
|
return [[a_from, a_to]]
|
21
88
|
end
|
22
89
|
|
23
|
-
#
|
90
|
+
# 3A. overlapping, A < B
|
24
91
|
if a_from < b_from and a_to < b_to and a_to >= b_from
|
25
92
|
return [[a_from, b_to]]
|
26
93
|
end
|
27
94
|
|
28
|
-
#
|
95
|
+
# 3B. overlapping, B < A
|
29
96
|
if b_from < a_from and b_to < a_to and b_to >= a_from
|
30
97
|
return [[b_from, a_to]]
|
31
98
|
end
|
data/ranges_merger.gemspec
CHANGED
@@ -5,12 +5,12 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "ranges_merger"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.1.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Aleksander Kwiatkowski"]
|
12
12
|
s.date = "2011-12-04"
|
13
|
-
s.description = "Simple gem used for merging range-like objects"
|
13
|
+
s.description = "Simple gem used for merging range-like objects. If you have problems with operations on ranges this gem can save you some time."
|
14
14
|
s.email = "bobikx@poczta.fm"
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"LICENSE.txt",
|
data/spec/ranges_merger_spec.rb
CHANGED
@@ -1,31 +1,149 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
2
|
|
3
3
|
describe "RangesMerger" do
|
4
|
-
it "should merge 2 overlapping" do
|
4
|
+
it "should merge 2 overlapping ranges" do
|
5
5
|
a = [1, 3]
|
6
6
|
b = [2, 4]
|
7
7
|
result = RangesMerger.two_way_merge([a, b])
|
8
8
|
result.should == [[1, 4]]
|
9
9
|
end
|
10
10
|
|
11
|
-
it "should merge 2
|
11
|
+
it "should merge 2 overlapping ranges" do
|
12
|
+
a = [2, 4]
|
13
|
+
b = [1, 3]
|
14
|
+
result = RangesMerger.two_way_merge([a, b])
|
15
|
+
result.should == [[1, 4]]
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should merge 2 not overlapping ranges" do
|
19
|
+
b = [1, 3]
|
20
|
+
a = [5, 6]
|
21
|
+
# it sorts :)
|
22
|
+
result = RangesMerger.two_way_merge([a, b])
|
23
|
+
result.should == [[1, 3], [5, 6]]
|
24
|
+
result.should_not == [[5, 6], [1, 3]]
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should merge 2 not overlapping ranges" do
|
12
28
|
a = [1, 3]
|
13
29
|
b = [5, 6]
|
14
30
|
result = RangesMerger.two_way_merge([a, b])
|
15
31
|
result.should == [[1, 3], [5, 6]]
|
16
32
|
end
|
17
33
|
|
18
|
-
it "should merge 2 identical" do
|
34
|
+
it "should merge 2 identical ranges" do
|
19
35
|
a = [1, 2]
|
20
36
|
b = [1, 2]
|
21
37
|
result = RangesMerger.two_way_merge([a, b])
|
22
38
|
result.should == [[1, 2]]
|
23
39
|
end
|
24
40
|
|
25
|
-
it "should merge 2
|
26
|
-
a = [
|
27
|
-
b = [
|
41
|
+
it "should merge 2 ranges, A within B" do
|
42
|
+
a = [1, 5]
|
43
|
+
b = [2, 3]
|
44
|
+
result = RangesMerger.two_way_merge([a, b])
|
45
|
+
result.should == [[1, 5]]
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should merge 2 ranges, B within A" do
|
49
|
+
b = [1, 5]
|
50
|
+
a = [2, 3]
|
28
51
|
result = RangesMerger.two_way_merge([a, b])
|
52
|
+
result.should == [[1, 5]]
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should merge 3 ranges (simple)" do
|
56
|
+
ranges = [[1, 2], [2, 3], [3, 4]]
|
57
|
+
result = RangesMerger.merge(ranges)
|
29
58
|
result.should == [[1, 4]]
|
30
59
|
end
|
60
|
+
|
61
|
+
it "should merge multiple (1)" do
|
62
|
+
ranges = [[0, 3], [3, 4], [1, 2], [10, 14], [12, 13]]
|
63
|
+
result = RangesMerger.merge(ranges)
|
64
|
+
result.should == [[0, 4], [10, 14]]
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should merge multiple (2)" do
|
68
|
+
ranges = [
|
69
|
+
[2, 4],
|
70
|
+
[3, 5],
|
71
|
+
[6, 9],
|
72
|
+
[7, 8],
|
73
|
+
[8, 9]
|
74
|
+
]
|
75
|
+
result = RangesMerger.merge(ranges)
|
76
|
+
result.should == [[2, 5], [6, 9]]
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
it "should merge multiple (3)" do
|
81
|
+
ranges = [
|
82
|
+
[2, 10],
|
83
|
+
[3, 9],
|
84
|
+
[4, 8],
|
85
|
+
[5, 7],
|
86
|
+
[6, 6]
|
87
|
+
]
|
88
|
+
result = RangesMerger.merge(ranges)
|
89
|
+
result.should == [[2, 10]]
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
it "should merge multiple (3)" do
|
94
|
+
ranges = [
|
95
|
+
[1, 100],
|
96
|
+
[2, 200],
|
97
|
+
[3, 500],
|
98
|
+
[200, 201],
|
99
|
+
[100, 2001]
|
100
|
+
]
|
101
|
+
result = RangesMerger.merge(ranges)
|
102
|
+
result.should == [[1, 2001]]
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should do the readme code" do
|
106
|
+
a = [1, 3]
|
107
|
+
b = [2, 4]
|
108
|
+
result = RangesMerger.two_way_merge([a, b])
|
109
|
+
result.should == [[1, 4]]
|
110
|
+
|
111
|
+
a = [1, 3]
|
112
|
+
b = [2, 4]
|
113
|
+
c = [4, 6]
|
114
|
+
result = RangesMerger.merge([a, b, c])
|
115
|
+
result.should == [[1, 6]]
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should merge very big array" do
|
119
|
+
ranges = Array.new
|
120
|
+
(1..1000).each do |i|
|
121
|
+
ranges << [i, i + 10]
|
122
|
+
end
|
123
|
+
result = RangesMerger.merge(ranges)
|
124
|
+
result.should == [[1, 1000 + 10]]
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should merge very big array (2)" do
|
128
|
+
ranges = Array.new
|
129
|
+
(1..1000).each do |i|
|
130
|
+
ranges << [10*i, 10*i + 1]
|
131
|
+
end
|
132
|
+
result = RangesMerger.merge(ranges)
|
133
|
+
result.size.should == 1000
|
134
|
+
result[0][0].should == 10
|
135
|
+
result.last[1].should == 1000*10 + 1
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should merge Range objects" do
|
139
|
+
ranges = [
|
140
|
+
(1..2),
|
141
|
+
(2..3),
|
142
|
+
(5..8)
|
143
|
+
]
|
144
|
+
result = RangesMerger.merge(ranges)
|
145
|
+
result.should == [(1..3),(5..8)]
|
146
|
+
end
|
147
|
+
|
148
|
+
|
31
149
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ranges_merger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ date: 2011-12-04 00:00:00.000000000Z
|
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &75213000 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 2.3.0
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *75213000
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: bundler
|
27
|
-
requirement: &
|
27
|
+
requirement: &75212750 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 1.0.0
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *75212750
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: jeweler
|
38
|
-
requirement: &
|
38
|
+
requirement: &75212470 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: 1.6.4
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *75212470
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rcov
|
49
|
-
requirement: &
|
49
|
+
requirement: &75212230 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,8 +54,9 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
58
|
-
description: Simple gem used for merging range-like objects
|
57
|
+
version_requirements: *75212230
|
58
|
+
description: Simple gem used for merging range-like objects. If you have problems
|
59
|
+
with operations on ranges this gem can save you some time.
|
59
60
|
email: bobikx@poczta.fm
|
60
61
|
executables: []
|
61
62
|
extensions: []
|
@@ -91,7 +92,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
91
92
|
version: '0'
|
92
93
|
segments:
|
93
94
|
- 0
|
94
|
-
hash:
|
95
|
+
hash: 63330927
|
95
96
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
97
|
none: false
|
97
98
|
requirements:
|