double_linked_list 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +30 -2
- data/Gemfile +2 -0
- data/README.md +79 -9
- data/double_linked_list.gemspec +1 -0
- data/lib/double_linked_list/element.rb +100 -0
- data/lib/double_linked_list/sequence.rb +18 -0
- data/lib/double_linked_list/version.rb +1 -1
- data/lib/double_linked_list.rb +40 -32
- metadata +19 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2d32b4473a261613c917ec8481da96bc7eaca8e4
|
4
|
+
data.tar.gz: 60e714c5a3baf1318412f3c5817f373ddc0e6d57
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 885e97ebc16d00e86142e1c5bc4ca6a9d4b9e7528be2e7bba8d618b18f2b1a2bb80613a167673a6bccdf56142efceebc6189fb34265a1bd29186108a4201d721
|
7
|
+
data.tar.gz: 682228a274f17a1849fc1824ec71a3778f5b93b07739e0878e2ae3af74e996b80e42b0ac3c8fde4f2f932a360d4ed84e9939cc3b404cd3b0df8f26f76192d3fd
|
data/.travis.yml
CHANGED
@@ -1,5 +1,33 @@
|
|
1
1
|
sudo: false
|
2
|
+
cache: bundler
|
2
3
|
language: ruby
|
3
4
|
rvm:
|
4
|
-
- 2.
|
5
|
-
|
5
|
+
- 2.1
|
6
|
+
- 2.1.6
|
7
|
+
- 2.2
|
8
|
+
- 2.3.0
|
9
|
+
- ruby-head
|
10
|
+
- jruby-19mode
|
11
|
+
- jruby-9.0.1.0
|
12
|
+
- rbx-3
|
13
|
+
env:
|
14
|
+
# this doesn't do anything for MRI or RBX, but it doesn't hurt them either
|
15
|
+
# for JRuby, it enables us to get more accurate coverage data
|
16
|
+
- JRUBY_OPTS="--debug"
|
17
|
+
matrix:
|
18
|
+
allow_failures:
|
19
|
+
- rvm: ruby-head
|
20
|
+
- rvm: rbx-3
|
21
|
+
- rvm: jruby-19mode
|
22
|
+
- rvm: jruby-9.0.1.0
|
23
|
+
- rvm: 1.9.3
|
24
|
+
- rvm: 2.0.0
|
25
|
+
fast_finish: true
|
26
|
+
before_install: gem update --remote bundler
|
27
|
+
install:
|
28
|
+
- bundle install --retry=3
|
29
|
+
script:
|
30
|
+
- bundle exec rspec
|
31
|
+
addons:
|
32
|
+
code_climate:
|
33
|
+
repo_token: 9bc6cf480824676f6f459544eb93d3ad09b4a69e9b42c57c5e657748c38b779a
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# DoubleLinkedList
|
2
2
|
|
3
|
+
[![Build Status](https://travis-ci.org/arturictus/double_linked_list.svg?branch=master)](https://travis-ci.org/arturictus/double_linked_list)
|
4
|
+
[![Gem Version](https://badge.fury.io/rb/double_linked_list.svg)](https://badge.fury.io/rb/double_linked_list)
|
5
|
+
[![Code Climate](https://codeclimate.com/github/arturictus/double_linked_list/badges/gpa.svg)](https://codeclimate.com/github/arturictus/double_linked_list)
|
6
|
+
[![Test Coverage](https://codeclimate.com/github/arturictus/double_linked_list/badges/coverage.svg)](https://codeclimate.com/github/arturictus/double_linked_list/coverage)
|
7
|
+
[![Issue Count](https://codeclimate.com/github/arturictus/double_linked_list/badges/issue_count.svg)](https://codeclimate.com/github/arturictus/double_linked_list)
|
8
|
+
|
3
9
|
The missing Ruby Linked list
|
4
10
|
|
5
11
|
## Installation
|
@@ -39,7 +45,7 @@ llist = DoubleLinkedList.from_a(1, 2, 3)
|
|
39
45
|
llist.last.datum #=> 3
|
40
46
|
```
|
41
47
|
|
42
|
-
__find:
|
48
|
+
__find:__
|
43
49
|
|
44
50
|
```ruby
|
45
51
|
llist = DoubleLinkedList.from_a(1, 2, 3)
|
@@ -50,13 +56,16 @@ llist.find(3).datum #=> 3
|
|
50
56
|
llist.find(9) #=> nil
|
51
57
|
```
|
52
58
|
|
53
|
-
|
54
|
-
|
59
|
+
__find_by:__
|
55
60
|
```ruby
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
61
|
+
User = Struct.new(:id)
|
62
|
+
users = [
|
63
|
+
User.new(1),
|
64
|
+
User.new(2),
|
65
|
+
User.new(3)
|
66
|
+
]
|
67
|
+
llist = DoubleLinkedList.from_a(users)
|
68
|
+
llist.find_by{ |elem| elem.datum.id == 1 }.datum.id #=> 1
|
60
69
|
```
|
61
70
|
|
62
71
|
__append:__
|
@@ -69,13 +78,74 @@ llist.last.next #=> be_nil
|
|
69
78
|
llist.last.previous.datum #=> 3
|
70
79
|
```
|
71
80
|
|
81
|
+
## Enumerable
|
82
|
+
|
83
|
+
- `map`
|
84
|
+
- `each`
|
85
|
+
- `reverse_each`
|
86
|
+
|
87
|
+
__each:__
|
88
|
+
```ruby
|
89
|
+
DoubleLinkedList.from_a(1, 2, 3).each { |e| puts e.datum }
|
90
|
+
# 1
|
91
|
+
# 2
|
92
|
+
# 3
|
93
|
+
```
|
94
|
+
|
95
|
+
__map:__
|
96
|
+
```ruby
|
97
|
+
DoubleLinkedList.from_a(1, 2, 3).map { |e| e.datum + 1}
|
98
|
+
#=> [2, 3, 4]
|
99
|
+
```
|
100
|
+
|
101
|
+
__reverse_each:__
|
102
|
+
```ruby
|
103
|
+
DoubleLinkedList.from_a(1, 2, 3).reverse_each { |e| puts e.datum }
|
104
|
+
# 3
|
105
|
+
# 2
|
106
|
+
# 1
|
107
|
+
```
|
108
|
+
|
109
|
+
__chunk_by:__
|
110
|
+
|
111
|
+
It will split the Double linked list in multiple linked list if the block
|
112
|
+
returns `truly`.
|
113
|
+
The first element of the splitted array are the elememts that return true in the block.
|
114
|
+
|
115
|
+
```ruby
|
116
|
+
llist = DoubleLinkedList.from_a(1, 2, 3, 4)
|
117
|
+
chunked = llist.chunk_by do |e, current_llist|
|
118
|
+
e.datum == 3 && current_llist.head.datum == 1
|
119
|
+
end
|
120
|
+
chunked.first.is_a? DoubleLinkedList #=> true
|
121
|
+
chunked.first.head.datum #=> 1
|
122
|
+
chunked.first.last.datum #=> 2
|
123
|
+
chunked.map{|ll| ll.to_a } #=> [[1, 2], [3, 4]]
|
124
|
+
```
|
125
|
+
|
126
|
+
__select_by:__
|
127
|
+
|
128
|
+
For selecting fractions of the linked list avoiding the elements not returned in between the selected head and last sequences.
|
129
|
+
In the block must be returned a `DoubleLinkedList::Sequence` instance and head and last in the `DoubleLinkedList::Sequence` must be a `DoubleLinkedList::Element` (the element is passed to the block)
|
130
|
+
|
131
|
+
```ruby
|
132
|
+
llist = DoubleLinkedList.from_a(1, 2, 3, 4)
|
133
|
+
select = llist.select_by do |e|
|
134
|
+
if e.datum == 2 && e.next.datum == 3
|
135
|
+
DoubleLinkedList::Sequence.new(head: e, last: e.next)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
select.is_a? Array #=> true
|
139
|
+
select.first.is_a? DoubleLinkedList #=> true
|
140
|
+
select.map{|ll| ll.to_a } #=> [[2, 3]]
|
141
|
+
```
|
72
142
|
|
73
143
|
## Development
|
74
144
|
|
75
145
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake false ---` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
76
146
|
|
77
|
-
To install this gem onto your local machine, run `bundle exec rake install`.
|
147
|
+
To install this gem onto your local machine, run `bundle exec rake install`. [rubygems.org](https://rubygems.org).
|
78
148
|
|
79
149
|
## Contributing
|
80
150
|
|
81
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
151
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/arturictus/double_linked_list.
|
data/double_linked_list.gemspec
CHANGED
@@ -21,5 +21,6 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.add_development_dependency "bundler", "~> 1.12"
|
22
22
|
spec.add_development_dependency "rake", "~> 10.0"
|
23
23
|
spec.add_development_dependency "rspec", "~> 3.5"
|
24
|
+
spec.add_development_dependency "contextuable"
|
24
25
|
# spec.add_development_dependency "false ---", "~> "
|
25
26
|
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
class DoubleLinkedList
|
2
|
+
class Element < Struct.new(:datum, :previous, :_next)
|
3
|
+
include Enumerable
|
4
|
+
alias_method :next, :_next
|
5
|
+
alias_method :prev, :previous
|
6
|
+
|
7
|
+
def each(&block)
|
8
|
+
block.call self
|
9
|
+
_next.each(&block) if _next
|
10
|
+
end
|
11
|
+
|
12
|
+
def find(datum)
|
13
|
+
find_next_by do |elem|
|
14
|
+
elem.datum == datum
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def find_previous_by(&block)
|
19
|
+
_finder(:reverse_each, &block)
|
20
|
+
end
|
21
|
+
|
22
|
+
def find_next_by(&block)
|
23
|
+
_finder(:each, &block)
|
24
|
+
end
|
25
|
+
|
26
|
+
def reverse_each(&block)
|
27
|
+
block.call self
|
28
|
+
previous.reverse_each(&block) if previous
|
29
|
+
end
|
30
|
+
|
31
|
+
def append(datum)
|
32
|
+
new_last = Element.new(datum, self, nil)
|
33
|
+
self._next = new_last
|
34
|
+
new_last
|
35
|
+
end
|
36
|
+
|
37
|
+
def chunk_by(acc, &block)
|
38
|
+
if acc.empty?
|
39
|
+
acc << DoubleLinkedList.from_a(self.datum)
|
40
|
+
else
|
41
|
+
if block.call(self, acc.last, acc)
|
42
|
+
acc << DoubleLinkedList.from_a(self.datum)
|
43
|
+
else
|
44
|
+
acc.last << self.datum
|
45
|
+
end
|
46
|
+
end
|
47
|
+
_next ? _next.chunk_by(acc, &block) : acc
|
48
|
+
end
|
49
|
+
|
50
|
+
def select_by(acc, &block)
|
51
|
+
sequences = []
|
52
|
+
find_multiple do |e|
|
53
|
+
head_tail = block.call(e)
|
54
|
+
if head_tail
|
55
|
+
sequences << head_tail
|
56
|
+
end
|
57
|
+
head_tail
|
58
|
+
end
|
59
|
+
extract_sequences(sequences)
|
60
|
+
end
|
61
|
+
|
62
|
+
protected
|
63
|
+
|
64
|
+
def find_multiple(&block)
|
65
|
+
found = each_until_found(&block)
|
66
|
+
found.next.find_multiple(&block) if found && found.next?
|
67
|
+
end
|
68
|
+
|
69
|
+
def each_until_found(&block)
|
70
|
+
found = block.call(self)
|
71
|
+
return found if found
|
72
|
+
_next.each_until_found(&block) if _next
|
73
|
+
end
|
74
|
+
|
75
|
+
def extract_sequences(sequences)
|
76
|
+
sequences.each_with_object([]) do |seq, coll|
|
77
|
+
head = seq.head
|
78
|
+
head_datum = head.datum
|
79
|
+
list = DoubleLinkedList.from_a(head_datum)
|
80
|
+
last = nil
|
81
|
+
head.find_multiple do |elem|
|
82
|
+
next if head_datum == elem.datum
|
83
|
+
list << elem.datum
|
84
|
+
last = elem.datum if elem.datum == seq.last.datum
|
85
|
+
break if last
|
86
|
+
end
|
87
|
+
coll << list
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def _finder(direction, &block)
|
92
|
+
found = nil
|
93
|
+
send(direction) do |elem|
|
94
|
+
found = elem if block.call(elem)
|
95
|
+
break if found
|
96
|
+
end
|
97
|
+
found
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class DoubleLinkedList
|
2
|
+
class Sequence
|
3
|
+
attr_reader :head, :last
|
4
|
+
def initialize(head:, last:)
|
5
|
+
@head = head
|
6
|
+
@last = last
|
7
|
+
end
|
8
|
+
|
9
|
+
def next
|
10
|
+
return unless next?
|
11
|
+
last.next
|
12
|
+
end
|
13
|
+
|
14
|
+
def next?
|
15
|
+
last.next ? true : false
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/double_linked_list.rb
CHANGED
@@ -3,7 +3,17 @@ require 'forwardable'
|
|
3
3
|
class DoubleLinkedList
|
4
4
|
extend Forwardable
|
5
5
|
attr_accessor :head, :last
|
6
|
-
delegate [
|
6
|
+
delegate [
|
7
|
+
:datum,
|
8
|
+
:next,
|
9
|
+
:map,
|
10
|
+
:each,
|
11
|
+
:reduce,
|
12
|
+
] => :head
|
13
|
+
|
14
|
+
delegate [
|
15
|
+
:reverse_each,
|
16
|
+
] => :last
|
7
17
|
|
8
18
|
def initialize(datum)
|
9
19
|
@head = (datum.is_a?(Element) ? datum : Element.new(datum))
|
@@ -11,8 +21,9 @@ class DoubleLinkedList
|
|
11
21
|
|
12
22
|
class << self
|
13
23
|
def from_a(*ary)
|
14
|
-
|
15
|
-
|
24
|
+
elems = ary.flatten
|
25
|
+
head = Element.new(elems.first)
|
26
|
+
last = elems.drop(1).reduce(head) do |cur_last, datum|
|
16
27
|
cur_last.append(datum)
|
17
28
|
end
|
18
29
|
new(head).tap do |o|
|
@@ -24,46 +35,43 @@ class DoubleLinkedList
|
|
24
35
|
def append(datum)
|
25
36
|
self.last = last.append(datum)
|
26
37
|
end
|
27
|
-
|
38
|
+
alias_method :<<, :append
|
28
39
|
|
29
40
|
def find(datum)
|
30
|
-
|
31
|
-
|
32
|
-
found = elem if elem.datum == datum
|
33
|
-
break if found
|
41
|
+
find_by do |elem|
|
42
|
+
elem.datum == datum
|
34
43
|
end
|
35
|
-
found
|
36
44
|
end
|
37
45
|
|
38
|
-
def
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
46
|
+
def find_by(&block)
|
47
|
+
head.find_next_by(&block)
|
48
|
+
end
|
49
|
+
|
50
|
+
def reverse_find(datum)
|
51
|
+
reverse_find_by do |elem|
|
52
|
+
elem.datum == datum
|
43
53
|
end
|
44
|
-
found
|
45
54
|
end
|
46
55
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
alias_method :prev, :previous
|
56
|
+
def reverse_find_by(&block)
|
57
|
+
last.find_previous_by(&block)
|
58
|
+
end
|
51
59
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
end
|
60
|
+
def chunk_by(&block)
|
61
|
+
head.chunk_by([], &block)
|
62
|
+
end
|
56
63
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
end
|
61
|
-
alias_method :reverse_each, :each_from_last
|
64
|
+
def select_by(&block)
|
65
|
+
head.select_by([], &block)
|
66
|
+
end
|
62
67
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
new_last
|
68
|
+
def to_a
|
69
|
+
[].tap do |ary|
|
70
|
+
each{ |elem| ary << elem.datum }
|
67
71
|
end
|
68
72
|
end
|
73
|
+
|
69
74
|
end
|
75
|
+
|
76
|
+
require 'double_linked_list/element'
|
77
|
+
require 'double_linked_list/sequence'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: double_linked_list
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Artur Pañach
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-11-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '3.5'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: contextuable
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
description: The missing Ruby Double Linked List.
|
56
70
|
email:
|
57
71
|
- arturictus@gmail.com
|
@@ -69,6 +83,8 @@ files:
|
|
69
83
|
- bin/setup
|
70
84
|
- double_linked_list.gemspec
|
71
85
|
- lib/double_linked_list.rb
|
86
|
+
- lib/double_linked_list/element.rb
|
87
|
+
- lib/double_linked_list/sequence.rb
|
72
88
|
- lib/double_linked_list/version.rb
|
73
89
|
homepage: https://github.com/arturictus/double_linked_list
|
74
90
|
licenses: []
|
@@ -89,7 +105,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
89
105
|
version: '0'
|
90
106
|
requirements: []
|
91
107
|
rubyforge_project:
|
92
|
-
rubygems_version: 2.
|
108
|
+
rubygems_version: 2.2.3
|
93
109
|
signing_key:
|
94
110
|
specification_version: 4
|
95
111
|
summary: The missing Ruby Double Linked List
|