fractional_indexer 0.4.0 → 0.4.1
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/README.md +260 -67
- data/lib/fractional_indexer/order_key.rb +2 -2
- data/lib/fractional_indexer/version.rb +1 -1
- metadata +12 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 647cdf5b4ac5ad3835667390221cfb694a37be44b50f494326ecc1a4d5a75b75
|
|
4
|
+
data.tar.gz: 3496c2e7f1132bb5699a26d614e9a66999733caeddd4b4d0c463cdcf2977848b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fdac9f7b6ebee39cdf765b81d5cb5c739632e1ad0b7de48e1b28f465a60a0b0afbdf1157ffe5df3f9ebddddca0d5b7d6c96323b5d80424e138ee36abcc1624da
|
|
7
|
+
data.tar.gz: 28bd39cf30678fed311bf1b9908ac76824b079859fa755bd8c2b181147ef3646dccbca8f257ee3ac763f0d2cff3f9f54b64bc398243d6ddcf7a3539a11da2155
|
data/README.md
CHANGED
|
@@ -3,13 +3,45 @@
|
|
|
3
3
|
[](https://codecov.io/gh/kazu-2020/fractional_indexer)
|
|
4
4
|
[](https://github.com/kazu-2020/fractional_indexer/actions/workflows/ruby.yml)
|
|
5
5
|
|
|
6
|
-
>
|
|
6
|
+
> Efficient data insertion and sorting through fractional indexing
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
## Overview
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Fractional Indexer is a Ruby gem that implements **fractional indexing** for managing ordered sequences. Instead of using integer positions that require reindexing on insertion, it uses string-based keys that allow inserting items anywhere without affecting existing items.
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
### Why Fractional Indexing?
|
|
13
|
+
|
|
14
|
+
**Traditional integer indexing** requires shifting all subsequent items when inserting:
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
Before: [A:1] [B:2] [C:3]
|
|
18
|
+
↓
|
|
19
|
+
Insert X between A and B
|
|
20
|
+
↓
|
|
21
|
+
After: [A:1] [X:2] [B:3] [C:4] ← B and C must be updated!
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Fractional indexing** generates a key between existing keys without reindexing:
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
Before: [A:"a0"] [B:"a1"] [C:"a2"]
|
|
28
|
+
↓
|
|
29
|
+
Insert X between A and B
|
|
30
|
+
↓
|
|
31
|
+
After: [A:"a0"] [X:"a0V"] [B:"a1"] [C:"a2"] ← No changes to B or C!
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Key Features
|
|
35
|
+
|
|
36
|
+
- **No reindexing required** - Insert items between any two existing items
|
|
37
|
+
- **String-based keys** - Avoids floating-point precision issues
|
|
38
|
+
- **Configurable base** - Supports base-10, base-62 (default), and base-94
|
|
39
|
+
- **Multiple key generation** - Generate multiple keys at once for batch operations
|
|
40
|
+
|
|
41
|
+
This gem implements the concepts from "[Realtime editing of ordered sequences](https://www.figma.com/blog/realtime-editing-of-ordered-sequences/#fractional-indexing)" (Figma Engineering Blog).
|
|
42
|
+
|
|
43
|
+
> [!TIP]
|
|
44
|
+
> **Using Rails?** Check out [narabikae](https://github.com/kazu-2020/narabikae) - an Active Record integration that makes fractional indexing as simple as `task.move_to_position_after(other_task)`
|
|
13
45
|
|
|
14
46
|
## Installation
|
|
15
47
|
|
|
@@ -31,135 +63,292 @@ Or install it yourself as:
|
|
|
31
63
|
gem install fractional_indexer
|
|
32
64
|
```
|
|
33
65
|
|
|
34
|
-
##
|
|
66
|
+
## Quick Start
|
|
67
|
+
|
|
68
|
+
```ruby
|
|
69
|
+
require 'fractional_indexer'
|
|
70
|
+
|
|
71
|
+
# Step 1: Generate your first key
|
|
72
|
+
first_key = FractionalIndexer.generate_key
|
|
73
|
+
# => "a0"
|
|
74
|
+
|
|
75
|
+
# Step 2: Generate the next key (for appending)
|
|
76
|
+
second_key = FractionalIndexer.generate_key(prev_key: first_key)
|
|
77
|
+
# => "a1"
|
|
78
|
+
|
|
79
|
+
# Step 3: Insert between two keys
|
|
80
|
+
middle_key = FractionalIndexer.generate_key(prev_key: first_key, next_key: second_key)
|
|
81
|
+
# => "a0V"
|
|
82
|
+
|
|
83
|
+
# Result: first_key < middle_key < second_key
|
|
84
|
+
# "a0" < "a0V" < "a1"
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## How It Works
|
|
88
|
+
|
|
89
|
+
### Order Key Structure
|
|
90
|
+
|
|
91
|
+
An order key consists of two parts: an **integer part** and an optional **fractional part**.
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
"a3012"
|
|
95
|
+
│└┬┘└┬┘
|
|
96
|
+
│ │ └── Fractional Part: "012" (optional, for fine-grained positioning)
|
|
97
|
+
│ └───── Integer Digits: "3" (the numeric value)
|
|
98
|
+
└─────── Prefix: "a" (indicates 1-digit positive integer)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Prefix rules:**
|
|
102
|
+
- `a` to `z`: Positive integers (a=1 digit, b=2 digits, ..., z=26 digits)
|
|
103
|
+
- `A` to `Z`: Negative integers (used for keys "before" zero)
|
|
104
|
+
|
|
105
|
+
**Examples:**
|
|
106
|
+
|
|
107
|
+
| Key | Integer Part | Fractional Part | Meaning |
|
|
108
|
+
|-----|-------------|-----------------|---------|
|
|
109
|
+
| `a5` | `a5` | (none) | Positive 1-digit: 5 |
|
|
110
|
+
| `b12` | `b12` | (none) | Positive 2-digit: 12 |
|
|
111
|
+
| `a3V` | `a3` | `V` | Between a3 and a4 |
|
|
112
|
+
| `Zz` | `Zz` | (none) | Largest negative number |
|
|
113
|
+
|
|
114
|
+
### Key Generation Flow
|
|
35
115
|
|
|
36
|
-
|
|
116
|
+
The following diagram shows how `generate_key` determines which operation to perform:
|
|
37
117
|
|
|
38
|
-
|
|
39
|
-
|
|
118
|
+
```mermaid
|
|
119
|
+
flowchart TD
|
|
120
|
+
A[generate_key] --> B{prev_key and next_key?}
|
|
121
|
+
B -->|Both nil| C["Return 'a0'<br/>(initial key)"]
|
|
122
|
+
B -->|Only prev_key| D["Increment<br/>(next key after prev)"]
|
|
123
|
+
B -->|Only next_key| E["Decrement<br/>(key before next)"]
|
|
124
|
+
B -->|Both provided| F["Midpoint<br/>(key between both)"]
|
|
40
125
|
|
|
41
|
-
|
|
126
|
+
D --> G["a0 → a1 → a2 → ..."]
|
|
127
|
+
E --> H["... → Zy → Zz → a0"]
|
|
128
|
+
F --> I["a0, a2 → a1<br/>a0, a1 → a0V"]
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Usage
|
|
132
|
+
|
|
133
|
+
### Basic Usage
|
|
134
|
+
|
|
135
|
+
#### Generating a Single Key
|
|
42
136
|
|
|
43
137
|
```ruby
|
|
44
138
|
require 'fractional_indexer'
|
|
45
139
|
|
|
46
|
-
#
|
|
140
|
+
# Create the first order key (when no keys exist)
|
|
47
141
|
FractionalIndexer.generate_key
|
|
48
142
|
# => "a0"
|
|
49
143
|
|
|
50
|
-
#
|
|
144
|
+
# Increment: generate key after a given key
|
|
51
145
|
FractionalIndexer.generate_key(prev_key: 'a0')
|
|
52
146
|
# => "a1"
|
|
53
147
|
|
|
54
|
-
#
|
|
148
|
+
# Decrement: generate key before a given key
|
|
55
149
|
FractionalIndexer.generate_key(next_key: 'a0')
|
|
56
150
|
# => "Zz"
|
|
57
151
|
|
|
58
|
-
# between
|
|
152
|
+
# Between: generate key between two keys
|
|
59
153
|
FractionalIndexer.generate_key(prev_key: 'a0', next_key: 'a2')
|
|
60
154
|
# => "a1"
|
|
61
|
-
|
|
62
|
-
# prev_key should be less than next_key
|
|
63
|
-
FractionalIndexer.generate_key(prev_key: 'a2', next_key: 'a1')
|
|
64
|
-
# => error
|
|
65
|
-
FractionalIndexer.generate_key(prev_key: 'a1', next_key: 'a1')
|
|
66
|
-
# => error
|
|
67
155
|
```
|
|
68
156
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
To generate multiple order keys, use the `FractionalIndexer.generate_keys` method.
|
|
157
|
+
#### Generating Multiple Keys
|
|
72
158
|
|
|
73
159
|
```ruby
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
# generate n order keys that sequentially follow a given prev_key.
|
|
160
|
+
# Generate 5 keys after "b11"
|
|
77
161
|
FractionalIndexer.generate_keys(prev_key: "b11", count: 5)
|
|
78
162
|
# => ["b12", "b13", "b14", "b15", "b16"]
|
|
79
163
|
|
|
80
|
-
#
|
|
164
|
+
# Generate 5 keys before "b11"
|
|
81
165
|
FractionalIndexer.generate_keys(next_key: "b11", count: 5)
|
|
82
166
|
# => ["b0w", "b0x", "b0y", "b0z", "b10"]
|
|
83
167
|
|
|
84
|
-
#
|
|
168
|
+
# Generate 5 keys between "b10" and "b11"
|
|
85
169
|
FractionalIndexer.generate_keys(prev_key: "b10", next_key: "b11", count: 5)
|
|
86
170
|
# => ["b108", "b10G", "b10V", "b10d", "b10l"]
|
|
87
171
|
```
|
|
88
172
|
|
|
89
|
-
|
|
173
|
+
#### Error Handling
|
|
90
174
|
|
|
91
|
-
|
|
175
|
+
```ruby
|
|
176
|
+
# prev_key must be less than next_key
|
|
177
|
+
FractionalIndexer.generate_key(prev_key: 'a2', next_key: 'a1')
|
|
178
|
+
# => raises error
|
|
179
|
+
|
|
180
|
+
# prev_key and next_key cannot be equal
|
|
181
|
+
FractionalIndexer.generate_key(prev_key: 'a1', next_key: 'a1')
|
|
182
|
+
# => raises error
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Practical Examples
|
|
186
|
+
|
|
187
|
+
#### Example 1: Task List Management
|
|
188
|
+
|
|
189
|
+
```ruby
|
|
190
|
+
# Managing a todo list with fractional indexing
|
|
191
|
+
tasks = []
|
|
192
|
+
|
|
193
|
+
# Add initial tasks
|
|
194
|
+
tasks << { id: 1, title: "Write code", position: FractionalIndexer.generate_key }
|
|
195
|
+
tasks << { id: 2, title: "Write tests", position: FractionalIndexer.generate_key(prev_key: tasks.last[:position]) }
|
|
196
|
+
tasks << { id: 3, title: "Deploy", position: FractionalIndexer.generate_key(prev_key: tasks.last[:position]) }
|
|
197
|
+
|
|
198
|
+
tasks.each { |t| puts "#{t[:position]}: #{t[:title]}" }
|
|
199
|
+
# a0: Write code
|
|
200
|
+
# a1: Write tests
|
|
201
|
+
# a2: Deploy
|
|
202
|
+
|
|
203
|
+
# Insert "Code review" between "Write tests" and "Deploy"
|
|
204
|
+
new_position = FractionalIndexer.generate_key(
|
|
205
|
+
prev_key: tasks[1][:position], # "a1"
|
|
206
|
+
next_key: tasks[2][:position] # "a2"
|
|
207
|
+
)
|
|
208
|
+
tasks << { id: 4, title: "Code review", position: new_position }
|
|
209
|
+
|
|
210
|
+
# Sort by position
|
|
211
|
+
tasks.sort_by! { |t| t[:position] }
|
|
212
|
+
tasks.each { |t| puts "#{t[:position]}: #{t[:title]}" }
|
|
213
|
+
# a0: Write code
|
|
214
|
+
# a1: Write tests
|
|
215
|
+
# a1V: Code review ← Inserted without changing other positions!
|
|
216
|
+
# a2: Deploy
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
#### Example 2: Prepending and Appending
|
|
92
220
|
|
|
93
|
-
|
|
94
|
-
|
|
221
|
+
```ruby
|
|
222
|
+
# Start with a middle item
|
|
223
|
+
items = [{ name: "B", pos: FractionalIndexer.generate_key }]
|
|
224
|
+
# items[0][:pos] => "a0"
|
|
225
|
+
|
|
226
|
+
# Append to the end (only prev_key)
|
|
227
|
+
items << { name: "C", pos: FractionalIndexer.generate_key(prev_key: items.last[:pos]) }
|
|
228
|
+
# items[1][:pos] => "a1"
|
|
229
|
+
|
|
230
|
+
# Prepend to the beginning (only next_key)
|
|
231
|
+
items.unshift({ name: "A", pos: FractionalIndexer.generate_key(next_key: items.first[:pos]) })
|
|
232
|
+
# items[0][:pos] => "Zz"
|
|
233
|
+
|
|
234
|
+
items.sort_by { |i| i[:pos] }.each { |i| puts "#{i[:pos]}: #{i[:name]}" }
|
|
235
|
+
# Zz: A
|
|
236
|
+
# a0: B
|
|
237
|
+
# a1: C
|
|
238
|
+
```
|
|
95
239
|
|
|
96
|
-
|
|
240
|
+
#### Example 3: Batch Insertion
|
|
241
|
+
|
|
242
|
+
```ruby
|
|
243
|
+
# Insert 5 items between two existing items at once
|
|
244
|
+
existing = [
|
|
245
|
+
{ name: "First", pos: "a0" },
|
|
246
|
+
{ name: "Last", pos: "a1" }
|
|
247
|
+
]
|
|
248
|
+
|
|
249
|
+
# Generate 5 keys between "a0" and "a1"
|
|
250
|
+
new_positions = FractionalIndexer.generate_keys(
|
|
251
|
+
prev_key: existing[0][:pos],
|
|
252
|
+
next_key: existing[1][:pos],
|
|
253
|
+
count: 5
|
|
254
|
+
)
|
|
255
|
+
# => ["a08", "a0G", "a0V", "a0d", "a0l"]
|
|
256
|
+
|
|
257
|
+
new_items = new_positions.map.with_index do |pos, i|
|
|
258
|
+
{ name: "Item #{i + 1}", pos: pos }
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
all_items = (existing + new_items).sort_by { |i| i[:pos] }
|
|
262
|
+
all_items.each { |i| puts "#{i[:pos]}: #{i[:name]}" }
|
|
263
|
+
# a0: First
|
|
264
|
+
# a08: Item 1
|
|
265
|
+
# a0G: Item 2
|
|
266
|
+
# a0V: Item 3
|
|
267
|
+
# a0d: Item 4
|
|
268
|
+
# a0l: Item 5
|
|
269
|
+
# a1: Last
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
#### Example 4: Key Growth Over Time
|
|
273
|
+
|
|
274
|
+
When repeatedly inserting at the same position, keys grow longer to maintain precision:
|
|
275
|
+
|
|
276
|
+
```ruby
|
|
277
|
+
# Repeatedly insert at the beginning
|
|
278
|
+
key = FractionalIndexer.generate_key # => "a0"
|
|
279
|
+
puts "Initial: #{key}"
|
|
280
|
+
|
|
281
|
+
5.times do |i|
|
|
282
|
+
key = FractionalIndexer.generate_key(prev_key: key, next_key: "a1")
|
|
283
|
+
puts "Insert #{i + 1}: #{key}"
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
# Initial: a0
|
|
287
|
+
# Insert 1: a0V
|
|
288
|
+
# Insert 2: a0l
|
|
289
|
+
# Insert 3: a0t
|
|
290
|
+
# Insert 4: a0x
|
|
291
|
+
# Insert 5: a0z
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## Configuration
|
|
295
|
+
|
|
296
|
+
### Base System
|
|
297
|
+
|
|
298
|
+
You can configure the base (number system) used to represent each digit. The possible values are `:base_10`, `:base_62` (default), and `:base_94`.
|
|
299
|
+
|
|
300
|
+
| Base | Characters | Use Case |
|
|
301
|
+
|------|-----------|----------|
|
|
302
|
+
| `:base_10` | `0-9` | Debugging, human-readable |
|
|
303
|
+
| `:base_62` | `0-9`, `A-Z`, `a-z` | General use (default) |
|
|
304
|
+
| `:base_94` | All printable ASCII | Maximum density |
|
|
97
305
|
|
|
98
306
|
```ruby
|
|
99
307
|
require 'fractional_indexer'
|
|
100
308
|
|
|
309
|
+
# Base 10 (for debugging)
|
|
101
310
|
FractionalIndexer.configure do |config|
|
|
102
311
|
config.base = :base_10
|
|
103
312
|
end
|
|
104
313
|
FractionalIndexer.configuration.digits.join
|
|
105
314
|
# => "0123456789"
|
|
106
315
|
|
|
316
|
+
# Base 62 (default)
|
|
107
317
|
FractionalIndexer.configure do |config|
|
|
108
318
|
config.base = :base_62
|
|
109
319
|
end
|
|
110
320
|
FractionalIndexer.configuration.digits.join
|
|
111
321
|
# => "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
|
112
322
|
|
|
323
|
+
# Base 94 (maximum density)
|
|
113
324
|
FractionalIndexer.configure do |config|
|
|
114
325
|
config.base = :base_94
|
|
115
326
|
end
|
|
116
327
|
FractionalIndexer.configuration.digits.join
|
|
117
|
-
# => "!\"
|
|
328
|
+
# => "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
|
|
118
329
|
```
|
|
119
330
|
|
|
120
|
-
##
|
|
121
|
-
|
|
122
|
-
This section explains the structure of the string that represents an Order Key.
|
|
123
|
-
An Order Key string is broadly divided into two parts: the integer part and the fractional part.
|
|
331
|
+
## Related Projects
|
|
124
332
|
|
|
125
|
-
|
|
333
|
+
### narabikae
|
|
126
334
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
The integer part of the Order Key begins with a `mandatory prefix` that indicates the number of digits. This prefix is represented by one of the letters A to Z or a to z.
|
|
130
|
-
a is 1 digit, b is 2 digits, c is 3 digits ...... and z represents 26 digits.
|
|
131
|
-
The number of characters following the prefix must match the number of digits indicated by the prefix.
|
|
132
|
-
For example, if the prefix is a, a valid key could be 'a8', and if the prefix is c, a valid key could be 'c135'.
|
|
335
|
+
If you're using **Ruby on Rails** with **Active Record**, check out [narabikae](https://github.com/kazu-2020/narabikae) - a gem that integrates Fractional Indexer directly into your models for seamless ordering.
|
|
133
336
|
|
|
134
337
|
```ruby
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
'c123' # Valid
|
|
139
|
-
'c12' # Invalid (The prefix 'c' requires three digits)
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
Additionally, leveraging the characteristic that uppercase letters have a lower ASCII value than lowercase letters, a to z represent positive integers, while A to Z represent negative integers.
|
|
143
|
-
|
|
144
|
-
### Fractional Part
|
|
145
|
-
|
|
146
|
-
The Fractional Part refers to the portion of the string that follows the Integer Part, excluding the Integer Part itself.
|
|
338
|
+
class Task < ApplicationRecord
|
|
339
|
+
narabikae :position, size: 200
|
|
340
|
+
end
|
|
147
341
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
# 'a3' : Integer Part
|
|
151
|
-
# '012': Fractional Part
|
|
152
|
-
```
|
|
342
|
+
# Move a task after another
|
|
343
|
+
task.move_to_position_after(other_task)
|
|
153
344
|
|
|
154
|
-
|
|
345
|
+
# Move a task before another
|
|
346
|
+
task.move_to_position_before(other_task)
|
|
155
347
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
'a320' # Invalid (The Fractional Part cannot end with '0' in base_10)
|
|
348
|
+
# Move a task between two others
|
|
349
|
+
task.move_to_position_between(task_a, task_b)
|
|
159
350
|
```
|
|
160
351
|
|
|
161
|
-
This section clarifies the concept and rules regarding the Fractional Part of an Order Key, with examples to illustrate what constitutes a valid or invalid Fractional Part.
|
|
162
|
-
|
|
163
352
|
## Contributing
|
|
164
353
|
|
|
165
354
|
Bug reports and pull requests are welcome on GitHub at <https://github.com/kazu-2020/fractional_indexer>.
|
|
@@ -167,3 +356,7 @@ Bug reports and pull requests are welcome on GitHub at <https://github.com/kazu-
|
|
|
167
356
|
## License
|
|
168
357
|
|
|
169
358
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
359
|
+
|
|
360
|
+
## Acknowledgments
|
|
361
|
+
|
|
362
|
+
This gem was implemented based on the excellent article "[Implementing Fractional Indexing](https://observablehq.com/@dgreensp/implementing-fractional-indexing)" by David Greenspan. Thank you for the clear explanation and reference implementation!
|
metadata
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fractional_indexer
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.4.
|
|
4
|
+
version: 0.4.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
|
-
-
|
|
8
|
-
|
|
9
|
-
bindir: exe
|
|
7
|
+
- matazou
|
|
8
|
+
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies: []
|
|
13
12
|
description: |
|
|
14
13
|
FractionalIndexer is a Ruby gem designed to leverage fractional indexing for ordering within lists or data structures.
|
|
15
14
|
it enables efficient sorting and insertion of large volumes of data.
|
|
16
15
|
email:
|
|
17
|
-
-
|
|
16
|
+
- 64774307+kazu-2020@users.noreply.github.com
|
|
18
17
|
executables: []
|
|
19
18
|
extensions: []
|
|
20
19
|
extra_rdoc_files: []
|
|
@@ -32,9 +31,12 @@ homepage: https://github.com/kazu-2020/fractional_indexer
|
|
|
32
31
|
licenses:
|
|
33
32
|
- MIT
|
|
34
33
|
metadata:
|
|
34
|
+
homepage_uri: https://github.com/kazu-2020/fractional_indexer
|
|
35
|
+
changelog_uri: https://github.com/kazu-2020/fractional_indexer/releases
|
|
36
|
+
bug_tracker_uri: https://github.com/kazu-2020/fractional_indexer/issues
|
|
35
37
|
source_code_uri: https://github.com/kazu-2020/fractional_indexer
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
allowed_push_host: https://rubygems.org/
|
|
39
|
+
rubygems_mfa_required: 'true'
|
|
38
40
|
rdoc_options: []
|
|
39
41
|
require_paths:
|
|
40
42
|
- lib
|
|
@@ -42,15 +44,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
42
44
|
requirements:
|
|
43
45
|
- - ">="
|
|
44
46
|
- !ruby/object:Gem::Version
|
|
45
|
-
version: '
|
|
47
|
+
version: '3.1'
|
|
46
48
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
47
49
|
requirements:
|
|
48
50
|
- - ">="
|
|
49
51
|
- !ruby/object:Gem::Version
|
|
50
52
|
version: '0'
|
|
51
53
|
requirements: []
|
|
52
|
-
rubygems_version: 3.
|
|
53
|
-
signing_key:
|
|
54
|
+
rubygems_version: 3.6.7
|
|
54
55
|
specification_version: 4
|
|
55
56
|
summary: efficient data insertion and sorting through fractional indexing
|
|
56
57
|
test_files: []
|