naturally 1.3.2 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 11b862eddf78c3c623300fc93d643a1b0081f815
4
- data.tar.gz: 576b16fec163a92e756c98c1df4f3b1af8ebab31
3
+ metadata.gz: a5b55ef725bab4abf9e87b176f86ab6c94d1ea4d
4
+ data.tar.gz: 2ca443c6027ed127aa570dceb2bdf63aeb060457
5
5
  SHA512:
6
- metadata.gz: 08f910f8cd088cb92969c6f1d257cc53a2178e54894639bac1b361651c986f312e90c6cd42eacb202b89fc664dbf1108d76b474578a40e0a35462bb6ab4f23fe
7
- data.tar.gz: 1f389ebe3746dc8d2f5c80cd35eb0dcdf4e408fd5f9116945e3355bdf2e037ecff46a60ca458bb3e02df5a701b3847460c184d4ba29012248aae2a09b32e26c9
6
+ metadata.gz: 85d8b14a18c0415b1360ce03a0eabad8e0cdfa07656648d71d251ac9556194aa705ff547b7cf5c6143762e876f425c4c05369047bef7368bdadaff24ce6d3705
7
+ data.tar.gz: df7f7705855241de8b0b1f4b26a4996398b90bfc5631088e5bcc9a141d2f98bc149a6192e9a19360b825839106ec06b3c12f586c327736b378eccb3f5c96694a
data/Gemfile CHANGED
@@ -1,8 +1,8 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  group :test do
4
- gem 'rspec', '~> 3.0'
5
- gem 'rake', '~> 10.0'
4
+ gem 'rspec', '~> 3'
5
+ gem 'rake', '~> 10'
6
6
  end
7
7
 
8
8
  # Specify your gem's dependencies in naturally.gemspec
data/README.md CHANGED
@@ -4,6 +4,11 @@
4
4
  Natural (version number) sorting with support for **legal document numbering**, **college course codes**, and **Unicode**.
5
5
  See Jeff Atwood's [Sorting for Humans: Natural Sort Order](http://www.codinghorror.com/blog/2007/12/sorting-for-humans-natural-sort-order.html) and the WebLaws.org post [Counting to 10 in Californian](http://www.weblaws.org/blog/2012/08/counting-from-1-to-10-in-californian/).
6
6
 
7
+ ##Installation
8
+
9
+ ```Shell
10
+ $ gem install naturally
11
+ ```
7
12
 
8
13
  ## Usage
9
14
 
@@ -11,7 +16,7 @@ See Jeff Atwood's [Sorting for Humans: Natural Sort Order](http://www.codinghorr
11
16
  require 'naturally'
12
17
 
13
18
  # Sort a simple array of strings
14
- Naturally.sort(["1.1", "1.10", "1.2"]) # => ["1.1", "1.2", "1.10"]
19
+ Naturally.sort(["336", "335a", "335", "335.1"]) # => ["335", "335.1", "335a", "336"]
15
20
  ```
16
21
 
17
22
  Usually the library is used to sort an array of objects:
@@ -45,7 +50,52 @@ expect(sorted.map(&:name)).to eq [
45
50
  ]
46
51
  ```
47
52
 
48
- See [the spec for more examples](https://github.com/dogweather/naturally/blob/master/spec/naturally_spec.rb) of what Naturally can sort.
53
+ [More examples are in the specs](https://github.com/dogweather/naturally/blob/master/spec/naturally_spec.rb).
54
+
55
+
56
+ ## Implementation Notes
57
+
58
+ The algorithm capitalizes on Ruby's array comparison behavior:
59
+ Since each dotted number actually represents a hierarchical
60
+ identifier, [array comparison](http://ruby-doc.org/core-2.2.1/Array.html#method-i-3C-3D-3E)
61
+ is a natural fit:
62
+
63
+ > Arrays are compared in an “element-wise” manner; the first element of ary is compared with the first one of other_ary using the <=> operator, then each of the second elements, etc… As soon as the result of any such comparison is non zero (i.e. the two corresponding elements are not equal), that result is returned for the whole array comparison.
64
+
65
+
66
+ And so, when given input such as,
67
+
68
+ ```ruby
69
+ ['1.9', '1.9a', '1.10']
70
+ ```
71
+
72
+ ...this module sorts the segmented numbers
73
+ by comparing them in their array forms:
74
+
75
+ ```ruby
76
+ [['1', '9'], ['1', '9a'], ['1', '10']]
77
+ ```
78
+
79
+ Finally, upon actual sort comparison, each of these strings is
80
+ converted to an array of typed objects. This is to determine the
81
+ sort order between heterogenous (yet ordered) segments such as
82
+ `'9a'` and `'9'`.
83
+
84
+ The final nested comparison structure looks like this:
85
+
86
+ ```ruby
87
+ [
88
+ [
89
+ [1], [9]
90
+ ],
91
+ [
92
+ [1], [9, 'a']
93
+ ],
94
+ [
95
+ [1], [10]
96
+ ]
97
+ ]
98
+ ```
49
99
 
50
100
  ## Related Work
51
101
 
@@ -2,11 +2,6 @@ require 'naturally/segment'
2
2
 
3
3
  # A module which performs natural sorting on a variety of number
4
4
  # formats. (See the specs for examples.)
5
- #
6
- # It achieves this by capitalizing on Ruby's behavior when
7
- # comparing arrays: The module sorts arrays of segmented numbers such as
8
- # ['1.9', '1.9a', '1.10'] by comparing them in their array forms.
9
- # I.e., approximately [['1', '9'], ['1, '9a'], ['1', '10']]
10
5
  module Naturally
11
6
  # Perform a natural sort.
12
7
  #
@@ -29,8 +24,8 @@ module Naturally
29
24
  # This enables it to be sorted against other arrays
30
25
  # by the standard #sort method.
31
26
  #
32
- # For example:
33
- # '1.2a.3' becomes [Segment<'1'>, Segment<'2a'>, Segment<'3'>]
27
+ # For example, '1.2a.3' becomes
28
+ # [Segment<'1'>, Segment<'2a'>, Segment<'3'>]
34
29
  #
35
30
  # @param [String] complex_number the number in a hierarchical form
36
31
  # such as 1.2a.3.
@@ -13,15 +13,30 @@ module Naturally
13
13
  to_array <=> other.to_array
14
14
  end
15
15
 
16
+ # @return [Array] a representation of myself in array form
17
+ # which enables me to be compared against
18
+ # another instance for sorting.
19
+ # The array is prepended with a symbol so
20
+ # two arrays are always comparable.
21
+ #
22
+ # @example a simple number
23
+ # Segment.new('10').to_array #=> [:int, 10]
24
+ #
25
+ # @example a college course code
26
+ # Segment.new('MATH101').to_array #=> [:str, "MATH", 101]
27
+ #
28
+ # @example Section 633a of the ADEA
29
+ # Segment.new('633a').to_array #=> [:int, 633, "a"]
16
30
  def to_array
31
+ # TODO: Refactor, probably via polymorphism
17
32
  if @val =~ /^(\p{Digit}+)(\p{Alpha}+)$/
18
- [$1.to_i, $2]
33
+ [:int, $1.to_i, $2]
19
34
  elsif @val =~ /^(\p{Alpha}+)(\p{Digit}+)$/
20
- [$1, $2.to_i]
35
+ [:str, $1, $2.to_i]
21
36
  elsif @val =~ /^\p{Digit}+$/
22
- [@val.to_i]
37
+ [:int, @val.to_i]
23
38
  else
24
- [@val]
39
+ [:str, @val]
25
40
  end
26
41
  end
27
42
  end
@@ -1,3 +1,4 @@
1
1
  module Naturally
2
- VERSION = '1.3.2'
2
+ # Gem version
3
+ VERSION = '1.4.0'
3
4
  end
@@ -1,4 +1,3 @@
1
- # -*- encoding: utf-8 -*-
2
1
  lib = File.expand_path('../lib', __FILE__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
3
  require 'naturally/version'
@@ -12,6 +11,7 @@ Gem::Specification.new do |gem|
12
11
  gem.summary = %q{Sorts numbers according to the way people are used to seeing them.}
13
12
  gem.description = %q{Natural Sorting with support for legal numbering, course numbers, and other number/letter mixes.}
14
13
  gem.homepage = "http://github.com/dogweather/naturally"
14
+ gem.required_ruby_version = '>= 2.1'
15
15
 
16
16
  gem.files = `git ls-files`.split($/)
17
17
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  require 'naturally'
3
2
 
4
3
  describe Naturally do
@@ -63,6 +62,34 @@ describe Naturally do
63
62
  to_this: %w(2 3 4 5 10 11 12 12а 12б 12в 13а 13б)
64
63
  )
65
64
  end
65
+
66
+ it 'sorts letters with digits correctly' do
67
+ it_sorts(
68
+ this: %w(1 a 2 b 3 c),
69
+ to_this: %w(1 2 3 a b c)
70
+ )
71
+ end
72
+
73
+ it 'sorts complex numbers with digits correctly' do
74
+ it_sorts(
75
+ this: %w(1 a 2 b 3 c 1.1 a.1 1.2 a.2 1.3 a.3 b.1 ),
76
+ to_this: %w(1 1.1 1.2 1.3 2 3 a a.1 a.2 a.3 b b.1 c)
77
+ )
78
+ end
79
+
80
+ it 'sorts complex mixes of numbers and digits correctly' do
81
+ it_sorts(
82
+ this: %w( 1.a.1 1.1 ),
83
+ to_this: %w( 1.1 1.a.1 )
84
+ )
85
+ end
86
+
87
+ it 'sorts complex mixes of numbers and digits correctly' do
88
+ it_sorts(
89
+ this: %w( 1a1 1aa aaa ),
90
+ to_this: %w( 1aa 1a1 aaa )
91
+ )
92
+ end
66
93
  end
67
94
 
68
95
  describe '#sort_naturally_by' do
@@ -109,5 +136,18 @@ describe Naturally do
109
136
  Париж
110
137
  )
111
138
  end
139
+
140
+ it 'sorts by an attribute which contains product names' do
141
+ Product = Struct.new(:name)
142
+ objects = [
143
+ Product.new('2 awesome decks'),
144
+ Product.new('Awesome deck')
145
+ ]
146
+ actual = Naturally.sort_by(objects, :name)
147
+ expect(actual.map(&:name)).to eq [
148
+ '2 awesome decks',
149
+ 'Awesome deck'
150
+ ]
151
+ end
112
152
  end
113
153
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: naturally
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.2
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robb Shecter
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-11 00:00:00.000000000 Z
11
+ date: 2015-08-04 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Natural Sorting with support for legal numbering, course numbers, and
14
14
  other number/letter mixes.
@@ -41,7 +41,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
41
41
  requirements:
42
42
  - - ">="
43
43
  - !ruby/object:Gem::Version
44
- version: '0'
44
+ version: '2.1'
45
45
  required_rubygems_version: !ruby/object:Gem::Requirement
46
46
  requirements:
47
47
  - - ">="
@@ -49,7 +49,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
49
49
  version: '0'
50
50
  requirements: []
51
51
  rubyforge_project:
52
- rubygems_version: 2.4.6
52
+ rubygems_version: 2.4.8
53
53
  signing_key:
54
54
  specification_version: 4
55
55
  summary: Sorts numbers according to the way people are used to seeing them.