unnatural 0.3.1 → 0.3.2
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 +5 -5
- data/.rubocop.yml +13 -0
- data/.travis.yml +2 -1
- data/lib/unnatural.rb +2 -1
- data/lib/unnatural/fast.rb +4 -0
- data/lib/unnatural/scan.rb +13 -1
- data/lib/unnatural/split.rb +3 -1
- data/lib/unnatural/substitution.rb +4 -1
- data/lib/unnatural/version.rb +1 -1
- data/unnatural.gemspec +5 -5
- metadata +8 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b3edc05b3b279add39a0b54112548568dc9a1ff96d77936737f57978912636ee
|
4
|
+
data.tar.gz: ce84b14bb28120e5806a1f370c05575ec949785fcaf3f80ffbe605d813021d3a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 02c2352f379dca9e31acfe4b9f8194d47de3571bf72ad69f60a87f12b6fdc3ea16152fff533282e386235e8a88e4c1c01c06b685301dd77c7439a081b53477b0
|
7
|
+
data.tar.gz: 4ce0601e48bf2854be2c08e554258e5fca14b6ecc167a6f3da8c0dde6adde410ff8e4dd9c1e352ef1941939862f01c4f19b5b84b664329003e9234427d2de401
|
data/.rubocop.yml
ADDED
data/.travis.yml
CHANGED
data/lib/unnatural.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'unnatural/version'
|
2
2
|
|
3
|
+
# A natural sort.
|
3
4
|
module Unnatural
|
4
5
|
def self.algorithms
|
5
6
|
[:Substitution, :Split, :Scan, :Fast]
|
@@ -20,7 +21,7 @@ module Unnatural
|
|
20
21
|
end
|
21
22
|
|
22
23
|
def self.sort_by(enumerable)
|
23
|
-
raise ArgumentError,
|
24
|
+
raise ArgumentError, 'Block expected but none given' unless block_given?
|
24
25
|
@algorithm.sort_by(enumerable) { |*a| yield(*a) }
|
25
26
|
end
|
26
27
|
|
data/lib/unnatural/fast.rb
CHANGED
@@ -2,7 +2,11 @@ require 'ffi'
|
|
2
2
|
require 'ffi-compiler/loader'
|
3
3
|
|
4
4
|
module Unnatural
|
5
|
+
# Compares strings byte-by-byte. Comparison function implemented in C. Does
|
6
|
+
# not appear to sort unicode strings correctly. Much faster than any of the
|
7
|
+
# pure Ruby options. The default.
|
5
8
|
module Fast
|
9
|
+
# module to hold the C function
|
6
10
|
module Ext
|
7
11
|
extend FFI::Library
|
8
12
|
ffi_lib FFI::Compiler::Loader.find('unnatural_ext')
|
data/lib/unnatural/scan.rb
CHANGED
@@ -1,19 +1,27 @@
|
|
1
1
|
require 'strscan'
|
2
2
|
|
3
3
|
module Unnatural
|
4
|
+
# Compares strings using a `StringScanner`. Pure ruby. Tends to be
|
5
|
+
# outperformed by `Unnatural::Substitution` and `Unnatural::Split` when
|
6
|
+
# sorting short strings via the global sort function, but its comparison
|
7
|
+
# function is the fastest of the pure-ruby algorithms.
|
4
8
|
module Scan
|
5
9
|
def self.sort(enumerable)
|
6
10
|
enumerable.sort { |a, b| compare(a, b) }
|
7
11
|
end
|
8
12
|
|
9
13
|
def self.sort_by(enumerable)
|
10
|
-
raise ArgumentError,
|
14
|
+
raise ArgumentError, 'Block expected but none given' unless block_given?
|
11
15
|
enumerable
|
12
16
|
.map { |e| [(yield e), e] }
|
13
17
|
.sort { |a, b| compare(a, b) }
|
14
18
|
.map { |ary| ary[1] }
|
15
19
|
end
|
16
20
|
|
21
|
+
# rubocop: disable Metrics/AbcSize
|
22
|
+
# rubocop: disable Metrics/CyclomaticComplexity
|
23
|
+
# rubocop: disable Metrics/MethodLength
|
24
|
+
# rubocop: disable Metrics/PerceivedComplexity
|
17
25
|
def self.compare(a_string, b_string)
|
18
26
|
if a_string.is_a?(Array) && b_string.is_a?(Array)
|
19
27
|
a_string = a_string.first
|
@@ -57,5 +65,9 @@ module Unnatural
|
|
57
65
|
return +1 if b.eos?
|
58
66
|
end
|
59
67
|
end
|
68
|
+
# rubocop: enable Metrics/AbcSize
|
69
|
+
# rubocop: enable Metrics/CyclomaticComplexity
|
70
|
+
# rubocop: enable Metrics/MethodLength
|
71
|
+
# rubocop: enable Metrics/PerceivedComplexity
|
60
72
|
end
|
61
73
|
end
|
data/lib/unnatural/split.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
module Unnatural
|
2
|
+
# Compares strings by spliting them into arrays of alternating string and
|
3
|
+
# integer values. Pure Ruby. Tends to be outperformed by the others.
|
2
4
|
module Split
|
3
5
|
SPLITTER = /(?<=\d)(?=\D)|(?<=\D)(?=\d)/
|
4
6
|
PRED = ['0'.ord.pred.chr].freeze
|
@@ -8,7 +10,7 @@ module Unnatural
|
|
8
10
|
end
|
9
11
|
|
10
12
|
def self.sort_by(enumerable)
|
11
|
-
raise ArgumentError,
|
13
|
+
raise ArgumentError, 'Block expected but none given' unless block_given?
|
12
14
|
enumerable.sort_by { |s| split(yield s) }
|
13
15
|
end
|
14
16
|
|
@@ -1,4 +1,7 @@
|
|
1
1
|
module Unnatural
|
2
|
+
# Compares strings by zero-padding integer sequences such that all are the
|
3
|
+
# same length. Pure Ruby. Tends to be outperformed by `Unnatural::Scan` on
|
4
|
+
# longer strings. Recommended for sorting short unicode strings.
|
2
5
|
module Substitution
|
3
6
|
def self.sort(enumerable)
|
4
7
|
largest = enumerable.map(&:size).max
|
@@ -6,7 +9,7 @@ module Unnatural
|
|
6
9
|
end
|
7
10
|
|
8
11
|
def self.sort_by(enumerable)
|
9
|
-
raise ArgumentError,
|
12
|
+
raise ArgumentError, 'Block expected but none given' unless block_given?
|
10
13
|
largest = enumerable.map { |e| yield e }.map(&:size).max
|
11
14
|
enumerable.sort_by { |s| substitute((yield s), largest) }
|
12
15
|
end
|
data/lib/unnatural/version.rb
CHANGED
data/unnatural.gemspec
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
|
2
2
|
lib = File.expand_path('../lib', __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
4
|
require 'unnatural/version'
|
@@ -10,11 +10,12 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.email = ['bjmllr@gmail.com']
|
11
11
|
|
12
12
|
spec.summary = 'A natural sort.'
|
13
|
-
spec.description
|
13
|
+
spec.description = 'A natural sort implementation with an emphasis on speed.'
|
14
14
|
spec.homepage = 'https://github.com/bjmllr/unnatural'
|
15
15
|
spec.license = 'MIT'
|
16
16
|
|
17
|
-
spec.files = `git ls-files -z
|
17
|
+
spec.files = `git ls-files -z`
|
18
|
+
.split("\x0")
|
18
19
|
.reject { |f| f.match(%r{^(test|spec|features)/}) }
|
19
20
|
spec.files += Dir.glob('ext/unnatural/*')
|
20
21
|
spec.require_paths = ['lib']
|
@@ -22,9 +23,8 @@ Gem::Specification.new do |spec|
|
|
22
23
|
spec.extensions = ['ext/unnatural/Rakefile']
|
23
24
|
|
24
25
|
spec.add_dependency 'ffi-compiler', '~> 1.0'
|
25
|
-
spec.add_dependency 'rake', '>= 9', '< 12'
|
26
26
|
|
27
|
+
spec.add_development_dependency 'benchmark-ips'
|
27
28
|
spec.add_development_dependency 'bundler', '~> 1.12'
|
28
29
|
spec.add_development_dependency 'minitest', '~> 5.0'
|
29
|
-
spec.add_development_dependency 'benchmark-ips'
|
30
30
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unnatural
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Miller
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-04-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi-compiler
|
@@ -25,25 +25,19 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: benchmark-ips
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
34
|
-
|
35
|
-
- !ruby/object:Gem::Version
|
36
|
-
version: '12'
|
37
|
-
type: :runtime
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
38
35
|
prerelease: false
|
39
36
|
version_requirements: !ruby/object:Gem::Requirement
|
40
37
|
requirements:
|
41
38
|
- - ">="
|
42
39
|
- !ruby/object:Gem::Version
|
43
|
-
version: '
|
44
|
-
- - "<"
|
45
|
-
- !ruby/object:Gem::Version
|
46
|
-
version: '12'
|
40
|
+
version: '0'
|
47
41
|
- !ruby/object:Gem::Dependency
|
48
42
|
name: bundler
|
49
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -72,20 +66,6 @@ dependencies:
|
|
72
66
|
- - "~>"
|
73
67
|
- !ruby/object:Gem::Version
|
74
68
|
version: '5.0'
|
75
|
-
- !ruby/object:Gem::Dependency
|
76
|
-
name: benchmark-ips
|
77
|
-
requirement: !ruby/object:Gem::Requirement
|
78
|
-
requirements:
|
79
|
-
- - ">="
|
80
|
-
- !ruby/object:Gem::Version
|
81
|
-
version: '0'
|
82
|
-
type: :development
|
83
|
-
prerelease: false
|
84
|
-
version_requirements: !ruby/object:Gem::Requirement
|
85
|
-
requirements:
|
86
|
-
- - ">="
|
87
|
-
- !ruby/object:Gem::Version
|
88
|
-
version: '0'
|
89
69
|
description: A natural sort implementation with an emphasis on speed.
|
90
70
|
email:
|
91
71
|
- bjmllr@gmail.com
|
@@ -95,6 +75,7 @@ extensions:
|
|
95
75
|
extra_rdoc_files: []
|
96
76
|
files:
|
97
77
|
- ".gitignore"
|
78
|
+
- ".rubocop.yml"
|
98
79
|
- ".travis.yml"
|
99
80
|
- CODE_OF_CONDUCT.md
|
100
81
|
- Gemfile
|
@@ -132,7 +113,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
132
113
|
version: '0'
|
133
114
|
requirements: []
|
134
115
|
rubyforge_project:
|
135
|
-
rubygems_version: 2.
|
116
|
+
rubygems_version: 2.7.3
|
136
117
|
signing_key:
|
137
118
|
specification_version: 4
|
138
119
|
summary: A natural sort.
|