unnatural 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ee0b35ed79162c58be6d1ed2af2022d18f19615d
4
- data.tar.gz: 4be5c919b28dd739b6d1cc4f9c2d8d01d49b6411
3
+ metadata.gz: e73154b350d906339b8003056791db6c5f94e098
4
+ data.tar.gz: ed95cd6dee1227b8f55cce433998685fd1b2c4bb
5
5
  SHA512:
6
- metadata.gz: 41c9475d5c6f7fb41dd962ddb1a11a2d5ac212d3186028a0d4b0c248efa91c8489a37f8973f9acbb2324e4fac62b14cdaee08990bb16b5530cf7c6e8c521cff2
7
- data.tar.gz: 5c19f5a7b5a05715d2967ea03104b3f3a7649d09bb7bac3476ea4d018707779f4f9ebd533ba8529fcb6e7ada69375a403aee9ec86017dbfdbc7c1d1eb719b1a9
6
+ metadata.gz: d0c8774280f8fdba7f71b1b39bbe63b6558a9a1b4659807b33a7c8b4acbb0c441739184e9155e0b440479fa29981403aad18bf3fc983eaca01c5d2e4fc1c5426
7
+ data.tar.gz: 96c913547575eb192399c6074237748c3defb54032fc0f5d4f3644293ba24a81c846e91589398ac09c1b6e19ad575284e2dc57c96327c1795fc02ca27e4beae8
data/README.md CHANGED
@@ -16,7 +16,7 @@ Unnatural does not (currently) provide support for:
16
16
  2. any number representation other than simple decimal integers
17
17
  3. whitespace insensitivity (i.e., one space and two spaces can be considered as different)
18
18
 
19
- Unnatural provides four algorithms, all of which use Ruby's built-in quicksort as the fundamental sort algorithm. All four modules provide module methods `.sort` for simply sorting an enumerable, and `.compare` for spaceship-operator-style comparison.
19
+ Unnatural provides four algorithms, all of which use Ruby's built-in quicksort as the fundamental sort algorithm. All four modules provide module methods `.sort` for simply sorting an enumerable, `.sort_by` for a memoized sort according to a block, and `.compare` for spaceship-operator-style comparison.
20
20
 
21
21
  ### Unnatural::Fast
22
22
 
@@ -59,6 +59,13 @@ require 'unnatural'
59
59
  sorted = Unnatural.sort(some_array_of_strings)
60
60
  ```
61
61
 
62
+ Sorting an enumerable of objects according to a block:
63
+
64
+ ```ruby
65
+ sorted = Unnatural.sort_by(some_array_of_objects) { |e| e.name }
66
+ sorted = Unnatural.sort_by(some_array_of_objects, &:name)
67
+ ```
68
+
62
69
  Defining the comparison method for a class explicitly:
63
70
 
64
71
  ```ruby
@@ -8,17 +8,28 @@ static VALUE rb_mFast;
8
8
  #define IS_LOWER(C) ('a' <= C && C <= 'z')
9
9
  #define UPCASE(C) (IS_LOWER(C) ? C - ('a' - 'A') : C)
10
10
 
11
- VALUE compare(VALUE self, VALUE a_value, VALUE b_value) {
12
- int a_length = RSTRING_LEN(a_value);
13
- int b_length = RSTRING_LEN(b_value);
14
- char* a_str = RSTRING_PTR(a_value);
15
- char* b_str = RSTRING_PTR(b_value);
16
- int a_pos = 0;
17
- int b_pos = 0;
18
- int a_number = 0;
19
- int b_number = 0;
20
- char a, b;
21
- int diff = 0;
11
+ VALUE compare(VALUE self, VALUE a_arg, VALUE b_arg) {
12
+ VALUE a_value, b_value;
13
+ int a_length, b_length, a_pos, b_pos, a_number, b_number, diff;
14
+ char *a_str, *b_str, a, b;
15
+
16
+ if (RB_TYPE_P(a_arg, T_ARRAY)) {
17
+ a_value = rb_ary_entry(a_arg, 0);
18
+ b_value = rb_ary_entry(b_arg, 0);
19
+ } else {
20
+ a_value = a_arg;
21
+ b_value = b_arg;
22
+ }
23
+
24
+ a_length = RSTRING_LEN(a_value);
25
+ b_length = RSTRING_LEN(b_value);
26
+ a_str = RSTRING_PTR(a_value);
27
+ b_str = RSTRING_PTR(b_value);
28
+ a_pos = 0;
29
+ b_pos = 0;
30
+ a_number = 0;
31
+ b_number = 0;
32
+ diff = 0;
22
33
 
23
34
  for (a_pos = 0, b_pos = 0; a_pos < a_length && b_pos < b_length; a_pos++, b_pos++) {
24
35
  a = a_str[a_pos];
@@ -6,6 +6,14 @@ unless RUBY_ENGINE == 'jruby'
6
6
  def self.sort(enumerable)
7
7
  enumerable.sort { |a, b| compare(a, b) }
8
8
  end
9
+
10
+ def self.sort_by(enumerable)
11
+ raise ArgumentError, "Block expected but none given" unless block_given?
12
+ enumerable
13
+ .map { |e| [(yield e), e] }
14
+ .sort { |a, b| compare(a, b) }
15
+ .map { |ary| ary[1] }
16
+ end
9
17
  end
10
18
  end
11
19
 
@@ -6,7 +6,20 @@ module Unnatural
6
6
  enumerable.sort { |a, b| compare(a, b) }
7
7
  end
8
8
 
9
+ def self.sort_by(enumerable)
10
+ raise ArgumentError, "Block expected but none given" unless block_given?
11
+ enumerable
12
+ .map { |e| [(yield e), e] }
13
+ .sort { |a, b| compare(a, b) }
14
+ .map { |ary| ary[1] }
15
+ end
16
+
9
17
  def self.compare(a_string, b_string)
18
+ if a_string.is_a?(Array) && b_string.is_a?(Array)
19
+ a_string = a_string.first
20
+ b_string = b_string.first
21
+ end
22
+
10
23
  a = StringScanner.new(a_string)
11
24
  b = StringScanner.new(b_string)
12
25
 
@@ -7,6 +7,11 @@ module Unnatural
7
7
  enumerable.sort_by { |s| split(s) }
8
8
  end
9
9
 
10
+ def self.sort_by(enumerable)
11
+ raise ArgumentError, "Block expected but none given" unless block_given?
12
+ enumerable.sort_by { |s| split(yield s) }
13
+ end
14
+
10
15
  def self.compare(a, b)
11
16
  split(a) <=> split(b)
12
17
  end
@@ -5,6 +5,12 @@ module Unnatural
5
5
  enumerable.sort_by { |s| substitute(s, largest) }
6
6
  end
7
7
 
8
+ def self.sort_by(enumerable)
9
+ raise ArgumentError, "Block expected but none given" unless block_given?
10
+ largest = enumerable.map { |e| yield e }.map(&:size).max
11
+ enumerable.sort_by { |s| substitute((yield s), largest) }
12
+ end
13
+
8
14
  def self.compare(a, b)
9
15
  largest = a.size < b.size ? b.size : a.size
10
16
  substitute(a, largest) <=> substitute(b, largest)
@@ -1,3 +1,3 @@
1
1
  module Unnatural
2
- VERSION = '0.1.0'.freeze
2
+ VERSION = '0.2.0'.freeze
3
3
  end
data/lib/unnatural.rb CHANGED
@@ -19,6 +19,11 @@ module Unnatural
19
19
  @algorithm.sort(enumerable)
20
20
  end
21
21
 
22
+ def self.sort_by(enumerable)
23
+ raise ArgumentError, "Block expected but none given" unless block_given?
24
+ @algorithm.sort_by(enumerable) { |*a| yield(*a) }
25
+ end
26
+
22
27
  def self.compare(a, b)
23
28
  @algorithm.compare(a, b)
24
29
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unnatural
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Miller