sorted_containers 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +0 -3
- data/README.md +127 -10
- data/lib/sorted_containers/sorted_array.rb +854 -0
- data/lib/sorted_containers/sorted_hash.rb +152 -0
- data/lib/sorted_containers/sorted_set.rb +82 -9
- data/lib/sorted_containers/version.rb +1 -1
- data/lib/sorted_containers.rb +2 -5
- metadata +9 -7
- data/lib/sorted_containers/sorted_list.rb +0 -174
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e7421a03c3463e6e190af04238230eca2120c195bcd711a8fc00eb0ed03ee662
|
4
|
+
data.tar.gz: 608647f3204d54ee2a0aeec7a77d3bd8050d8c14e78638b0f4edd604d61618f7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 45fdc56cd4e5593b218376240935d4ff31e3b3f010ece456e72a6334752a28a5f336852a367f8428f1967bbfee49f855ff2d7c14fb5f76af187f6bdf11ffc1ca
|
7
|
+
data.tar.gz: 405354a1b5125f4116348906a5694e66aab47d94e9aa3524335683a04c4cb96e0a0ae181ec164114a00f4fc9ccc8264c68ebf460074b45c0f8f74d2891246ef2
|
data/.rubocop.yml
CHANGED
data/README.md
CHANGED
@@ -1,24 +1,141 @@
|
|
1
1
|
# SortedContainers
|
2
2
|
|
3
|
-
|
3
|
+
SortedContainers is a fast implementation of sorted lists, sets, and dictionaries in pure Ruby. It is based on the [sortedcontainers](https://grantjenks.com/docs/sortedcontainers/) Python library by Grant Jenks.
|
4
4
|
|
5
|
-
|
5
|
+
SortedContainers provides three main classes: `SortedArray`, `SortedSet`, and `SortedHash`. Each class is a drop-in replacement for the corresponding Ruby class, but with the added benefit of maintaining the elements in sorted order.
|
6
|
+
|
7
|
+
SortedContainers exploits the fact that modern computers are really good at shifting arrays in memory. We sacrifice theroetical time complexity for practical performance. In practice, SortedContainers is fast.
|
8
|
+
|
9
|
+
## How it works
|
10
|
+
|
11
|
+
Computers are good at shifting arrays. For that reason, it's often faster to keep an array sorted than to use the usual tree-based data structures.
|
12
|
+
|
13
|
+
For example, if you have the array `[1, 2, 4, 5]` and want to insert the element `3`, you can shift `4, 5` to the right and insert `3` in the correct position. This is a `O(n)` operation, but in practice it's fast.
|
14
|
+
|
15
|
+
But we can do better if we have a lot of elements. We can break up the array into smaller arrays so the shifts don't have to move so many elements. For example, if you have the array `[[1,2,4], [5,6,7]]` and you want to insert the element `3`, you can insert `3` into the first array to get `[[1,2,3,4], [5,6,7]]` and only the element `4` has to be shifted.
|
16
|
+
|
17
|
+
This often outperforms the more common tree-based data structures like red-black trees with `O(log n)` insertions and deletions. In practice, the `O(n)` insertions and deletions of SortedContainers are faster.
|
18
|
+
|
19
|
+
How big the subarrays are is a trade-off. You can modify how big you want to subarrays by setting the `load_factor`. The default is set to DEFAULT_LOAD_FACTOR = 1000. The subarray is split when its size is `2*load_factor`. There is no perfect value. The ideal value will depend on your use case and may require some experimentation.
|
20
|
+
|
21
|
+
## Benchmarks
|
22
|
+
|
23
|
+
Performance comparison against [SortedSet](https://github.com/knu/sorted_set) a C extension red-black tree implementation. Every test was run 5 times and the average was taken.
|
24
|
+
|
25
|
+
You can see that SortedContainers has compariable performance for add and delete, and much better performance for iteration, initialization, and include.
|
26
|
+
|
27
|
+
Note: I do not know why initialization is faster for 4 million than 3 million elements. This was consistant across multiple runs.
|
28
|
+
|
29
|
+
- MacBook Pro (16-inch, 2019)
|
30
|
+
- 2.6 GHz 6-Core Intel Core i7, 16 GB 2667 MHz DDR4
|
31
|
+
- Ruby 3.2.2
|
32
|
+
- SortedContainers 0.1.0
|
33
|
+
- SortedSet 1.0.3
|
34
|
+
### Results (Lower is better)
|
35
|
+
<img src="benchmark/initialize_performance_comparison.png" width="50%">
|
36
|
+
<img src="benchmark/add_performance_comparison.png" width="50%">
|
37
|
+
<img src="benchmark/delete_performance_comparison.png" width="50%">
|
38
|
+
<img src="benchmark/iteration_performance_comparison.png" width="50%">
|
39
|
+
<img src="benchmark/include_performance_comparison.png" width="50%">
|
6
40
|
|
7
41
|
## Installation
|
8
42
|
|
9
|
-
|
43
|
+
Add this line to your application's Gemfile:
|
10
44
|
|
11
|
-
|
45
|
+
```ruby
|
46
|
+
gem 'sorted_containers'
|
47
|
+
```
|
12
48
|
|
13
|
-
|
49
|
+
And then execute:
|
14
50
|
|
15
|
-
|
51
|
+
```bash
|
52
|
+
bundle install
|
53
|
+
```
|
16
54
|
|
17
|
-
|
55
|
+
Or install it yourself as:
|
56
|
+
|
57
|
+
```bash
|
58
|
+
gem install sorted_containers
|
59
|
+
```
|
18
60
|
|
19
61
|
## Usage
|
20
62
|
|
21
|
-
|
63
|
+
require 'sorted_containers'
|
64
|
+
|
65
|
+
# Create a new SortedArray
|
66
|
+
list = SortedContainers::SortedArray.new
|
67
|
+
|
68
|
+
# Add elements to the list
|
69
|
+
list << 3
|
70
|
+
list << 1
|
71
|
+
list << 2
|
72
|
+
|
73
|
+
# Access elements by index
|
74
|
+
puts list[0] # => 1
|
75
|
+
puts list[1] # => 2
|
76
|
+
puts list[2] # => 3
|
77
|
+
|
78
|
+
# Access elements by index
|
79
|
+
puts list.first # => 1
|
80
|
+
puts list.last # => 3
|
81
|
+
|
82
|
+
# Remove elements from the list
|
83
|
+
list.delete(2)
|
84
|
+
|
85
|
+
# Iterate over the list
|
86
|
+
list.each do |element|
|
87
|
+
puts element
|
88
|
+
end
|
89
|
+
|
90
|
+
# Create a new SortedSet
|
91
|
+
set = SortedContainers::SortedSet.new
|
92
|
+
|
93
|
+
# Add elements to the set
|
94
|
+
set << 3
|
95
|
+
set << 1
|
96
|
+
set << 2
|
97
|
+
|
98
|
+
# Access elements by index
|
99
|
+
puts set[0] # => 1
|
100
|
+
puts set[1] # => 2
|
101
|
+
puts set[2] # => 3
|
102
|
+
|
103
|
+
# Access elements by index
|
104
|
+
puts set.first # => 1
|
105
|
+
puts set.last # => 3
|
106
|
+
|
107
|
+
# Remove elements from the set
|
108
|
+
set.delete(2)
|
109
|
+
|
110
|
+
# Iterate over the set
|
111
|
+
set.each do |element|
|
112
|
+
puts element
|
113
|
+
end
|
114
|
+
|
115
|
+
# Create a new SortedHash
|
116
|
+
dict = SortedContainers::SortedHash.new
|
117
|
+
|
118
|
+
# Add elements to the dict
|
119
|
+
dict[3] = 'three'
|
120
|
+
dict[1] = 'one'
|
121
|
+
dict[2] = 'two'
|
122
|
+
|
123
|
+
# Access elements by key
|
124
|
+
puts dict[1] # => 'one'
|
125
|
+
puts dict[2] # => 'two'
|
126
|
+
puts dict[3] # => 'three'
|
127
|
+
|
128
|
+
# Access elements by index
|
129
|
+
puts dict.first # => [1, 'one']
|
130
|
+
puts dict.last # => [3, 'three']
|
131
|
+
|
132
|
+
# Remove elements from the dict
|
133
|
+
dict.delete(2)
|
134
|
+
|
135
|
+
# Iterate over the dict
|
136
|
+
dict.each do |key, value|
|
137
|
+
puts "#{key}: #{value}"
|
138
|
+
end
|
22
139
|
|
23
140
|
## Development
|
24
141
|
|
@@ -28,7 +145,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
28
145
|
|
29
146
|
## Contributing
|
30
147
|
|
31
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
148
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/GarrisonJ/sorted_containers. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/GarrisonJ/sorted_containers/blob/main/CODE_OF_CONDUCT.md).
|
32
149
|
|
33
150
|
## License
|
34
151
|
|
@@ -36,4 +153,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
36
153
|
|
37
154
|
## Code of Conduct
|
38
155
|
|
39
|
-
Everyone interacting in the SortedContainers project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/
|
156
|
+
Everyone interacting in the SortedContainers project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/GarrisonJ/sorted_containers/blob/main/CODE_OF_CONDUCT.md).
|