unnatural 0.1.0 → 0.2.0
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 +8 -1
- data/ext/unnatural/fast_compare.c +22 -11
- data/lib/unnatural/fast.rb +8 -0
- data/lib/unnatural/scan.rb +13 -0
- data/lib/unnatural/split.rb +5 -0
- data/lib/unnatural/substitution.rb +6 -0
- data/lib/unnatural/version.rb +1 -1
- data/lib/unnatural.rb +5 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e73154b350d906339b8003056791db6c5f94e098
|
4
|
+
data.tar.gz: ed95cd6dee1227b8f55cce433998685fd1b2c4bb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
12
|
-
|
13
|
-
int b_length
|
14
|
-
char*
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
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];
|
data/lib/unnatural/fast.rb
CHANGED
@@ -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
|
|
data/lib/unnatural/scan.rb
CHANGED
@@ -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
|
|
data/lib/unnatural/split.rb
CHANGED
@@ -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)
|
data/lib/unnatural/version.rb
CHANGED
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
|