quality_extensions 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Readme +54 -0
- data/lib/qualitysmith_extensions/all.rb +4 -0
- data/lib/qualitysmith_extensions/array/all.rb +2 -0
- data/lib/qualitysmith_extensions/array/average.rb +44 -0
- data/lib/qualitysmith_extensions/array/classify.rb +97 -0
- data/lib/qualitysmith_extensions/array/expand_ranges.rb +52 -0
- data/lib/qualitysmith_extensions/array/group_by.rb +134 -0
- data/lib/qualitysmith_extensions/array/sequence.rb +66 -0
- data/lib/qualitysmith_extensions/array/shell_escape.rb +36 -0
- data/lib/qualitysmith_extensions/array/to_a_recursive.rb +41 -0
- data/lib/qualitysmith_extensions/array/to_query_string.rb +96 -0
- data/lib/qualitysmith_extensions/collection_extensions_for_cgi.rb +2 -0
- data/lib/qualitysmith_extensions/colored/toggleability.rb +62 -0
- data/lib/qualitysmith_extensions/console/command.facets.1.8.51.rb +749 -0
- data/lib/qualitysmith_extensions/console/command.facets.1.8.54.rb +748 -0
- data/lib/qualitysmith_extensions/console/command.rb +944 -0
- data/lib/qualitysmith_extensions/date/all.rb +2 -0
- data/lib/qualitysmith_extensions/date/deprecated.rb +40 -0
- data/lib/qualitysmith_extensions/date/iso8601.rb +31 -0
- data/lib/qualitysmith_extensions/date/month_ranges.rb +122 -0
- data/lib/qualitysmith_extensions/dir/each_child.rb +58 -0
- data/lib/qualitysmith_extensions/enumerable/enum.rb +69 -0
- data/lib/qualitysmith_extensions/enumerable/select_until.rb +4 -0
- data/lib/qualitysmith_extensions/enumerable/select_while.rb +109 -0
- data/lib/qualitysmith_extensions/exception/inspect_with_backtrace.rb +65 -0
- data/lib/qualitysmith_extensions/file/exact_match_regexp.rb +34 -0
- data/lib/qualitysmith_extensions/file_test/binary_file.rb +110 -0
- data/lib/qualitysmith_extensions/find/select.rb +68 -0
- data/lib/qualitysmith_extensions/global_variable_set.rb +153 -0
- data/lib/qualitysmith_extensions/hash/all.rb +2 -0
- data/lib/qualitysmith_extensions/hash/to_date.rb +34 -0
- data/lib/qualitysmith_extensions/hash/to_query_string.rb +121 -0
- data/lib/qualitysmith_extensions/kernel/all.rb +2 -0
- data/lib/qualitysmith_extensions/kernel/autoreload.rb +128 -0
- data/lib/qualitysmith_extensions/kernel/backtrace.rb +71 -0
- data/lib/qualitysmith_extensions/kernel/capture_output.rb +115 -0
- data/lib/qualitysmith_extensions/kernel/die.rb +49 -0
- data/lib/qualitysmith_extensions/kernel/example_printer.rb +81 -0
- data/lib/qualitysmith_extensions/kernel/filter_output.rb +108 -0
- data/lib/qualitysmith_extensions/kernel/remove_const.rb +178 -0
- data/lib/qualitysmith_extensions/kernel/remove_module.rb +127 -0
- data/lib/qualitysmith_extensions/kernel/require_all.rb +186 -0
- data/lib/qualitysmith_extensions/kernel/require_local_all.rb +4 -0
- data/lib/qualitysmith_extensions/kernel/require_once.rb +18 -0
- data/lib/qualitysmith_extensions/kernel/simulate_input.rb +52 -0
- data/lib/qualitysmith_extensions/kernel/trap_chain.rb +61 -0
- data/lib/qualitysmith_extensions/kernel/windows_platform.rb +46 -0
- data/lib/qualitysmith_extensions/module/alias_method.rb +6 -0
- data/lib/qualitysmith_extensions/module/alias_method_chain.rb +165 -0
- data/lib/qualitysmith_extensions/module/ancestry_of_instance_method.rb +43 -0
- data/lib/qualitysmith_extensions/module/attribute_accessors.rb +49 -0
- data/lib/qualitysmith_extensions/module/basename.rb +76 -0
- data/lib/qualitysmith_extensions/module/bool_attr_accessor.rb +497 -0
- data/lib/qualitysmith_extensions/module/class_methods.rb +87 -0
- data/lib/qualitysmith_extensions/module/create.rb +315 -0
- data/lib/qualitysmith_extensions/module/create_setter.rb +9 -0
- data/lib/qualitysmith_extensions/module/dirname.rb +4 -0
- data/lib/qualitysmith_extensions/module/guard_method.rb +312 -0
- data/lib/qualitysmith_extensions/module/includable_once.rb +10 -0
- data/lib/qualitysmith_extensions/module/join.rb +66 -0
- data/lib/qualitysmith_extensions/module/malias_method_chain.rb +92 -0
- data/lib/qualitysmith_extensions/module/module_methods.rb +4 -0
- data/lib/qualitysmith_extensions/module/namespace.rb +112 -0
- data/lib/qualitysmith_extensions/module/parents.rb +61 -0
- data/lib/qualitysmith_extensions/module/remove_const.rb +117 -0
- data/lib/qualitysmith_extensions/module/split.rb +55 -0
- data/lib/qualitysmith_extensions/month.rb +66 -0
- data/lib/qualitysmith_extensions/mutex/if_available.rb +75 -0
- data/lib/qualitysmith_extensions/object/ancestry_of_method.rb +257 -0
- data/lib/qualitysmith_extensions/object/default.rb +69 -0
- data/lib/qualitysmith_extensions/object/if_else.rb +157 -0
- data/lib/qualitysmith_extensions/object/ignore_access.rb +84 -0
- data/lib/qualitysmith_extensions/object/mcall.rb +92 -0
- data/lib/qualitysmith_extensions/object/methods.rb +63 -0
- data/lib/qualitysmith_extensions/object/send_if.rb +151 -0
- data/lib/qualitysmith_extensions/object/send_if_not_nil.rb +35 -0
- data/lib/qualitysmith_extensions/object/singleton_send.rb +129 -0
- data/lib/qualitysmith_extensions/regexp/join.rb +111 -0
- data/lib/qualitysmith_extensions/string/all.rb +2 -0
- data/lib/qualitysmith_extensions/string/constantize.rb +4 -0
- data/lib/qualitysmith_extensions/string/digits_only.rb +27 -0
- data/lib/qualitysmith_extensions/string/each_char_with_index.rb +41 -0
- data/lib/qualitysmith_extensions/string/md5.rb +29 -0
- data/lib/qualitysmith_extensions/string/shell_escape.rb +43 -0
- data/lib/qualitysmith_extensions/string/to_underscored_label.rb +37 -0
- data/lib/qualitysmith_extensions/string/with_knowledge_of_color.rb +64 -0
- data/lib/qualitysmith_extensions/symbol/constantize.rb +69 -0
- data/lib/qualitysmith_extensions/symbol/match.rb +157 -0
- data/lib/qualitysmith_extensions/template.rb +33 -0
- data/lib/qualitysmith_extensions/test/all.rb +2 -0
- data/lib/qualitysmith_extensions/test/assert_anything.rb +93 -0
- data/lib/qualitysmith_extensions/test/assert_changed.rb +66 -0
- data/lib/qualitysmith_extensions/test/assert_exception.rb +66 -0
- data/lib/qualitysmith_extensions/test/assert_includes.rb +36 -0
- data/lib/qualitysmith_extensions/test/assert_user_error.rb +37 -0
- data/lib/qualitysmith_extensions/test/difference_highlighting.rb +323 -0
- data/lib/qualitysmith_extensions/time/all.rb +2 -0
- data/lib/qualitysmith_extensions/time/deprecated.rb +31 -0
- data/test/all.rb +16 -0
- metadata +148 -0
data/Readme
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
= QualitySmith Extensions
|
2
|
+
|
3
|
+
[<b>Home page</b>:] http://qualitysmithext.rubyforge.org/
|
4
|
+
[<b>Project site</b>:] http://rubyforge.org/projects/qualitysmithext/
|
5
|
+
[<b>Gem install</b>:] <tt>gem install qualitysmith_extensions</tt>
|
6
|
+
[<b>License</b>:] {Ruby License}[link:files/License.html]
|
7
|
+
|
8
|
+
== Introduction
|
9
|
+
|
10
|
+
This is a library of miscellaneous general-purpose, reusable Ruby code, quite similar in purpose and layout to {Ruby Facets}[http://facets.rubyforge.org/]. It is certainly not meant to _compete_ with Facets though!
|
11
|
+
|
12
|
+
Developers are encouraged to first check if the method or class they are looking for already exists in one of the fine existing open-source projects (like {Facets}[http://facets.rubyforge.org/] or {Extensions}[http://extensions.rubyforge.org/rdoc/index.html] or {stdlib}[http://www.ruby-doc.org/stdlib/]).
|
13
|
+
|
14
|
+
If the code you are needing hasn't already been written by someone else, then you can throw it in this library. Also submit it to an existing extensions project if you think it's any good.
|
15
|
+
|
16
|
+
Like Facets, this library contains:
|
17
|
+
* methods that add functionality to existing Ruby classes (String, Array, etc.)
|
18
|
+
* as well as new classes that aren't in core Ruby
|
19
|
+
|
20
|
+
== Installation
|
21
|
+
|
22
|
+
gem install qualitysmith_extensions
|
23
|
+
|
24
|
+
== Usage
|
25
|
+
|
26
|
+
require 'rubygems'
|
27
|
+
gem 'qualitysmith_extensions'
|
28
|
+
|
29
|
+
And then <b>include as much or as little as you want</b>.
|
30
|
+
|
31
|
+
Use the handy <tt>all.rb</tt> files to load everything in a particular directory (and all subdirectories).
|
32
|
+
|
33
|
+
To load everything:
|
34
|
+
|
35
|
+
require 'qualitysmith_extensions/all'
|
36
|
+
|
37
|
+
To load everything just for one class:
|
38
|
+
|
39
|
+
require 'qualitysmith_extensions/string/all'
|
40
|
+
|
41
|
+
To load just an individual method:
|
42
|
+
|
43
|
+
require 'qualitysmith_extensions/array/average'
|
44
|
+
|
45
|
+
|
46
|
+
== Running tests
|
47
|
+
|
48
|
+
Tests are self-contained within the file for the code that is under test.
|
49
|
+
|
50
|
+
To run the tests directly, you need to use the <tt>exrb</tt> command that is part of the {Ratchets}[http://ratchets.rubyforge.org/] project.
|
51
|
+
|
52
|
+
At some point in time, we may extract them into separate files using the Exacto test extractor tool.
|
53
|
+
|
54
|
+
<b>QualitySmith developers</b>: If you use <tt>vim</tt>, you can set up your editor to run the tests just by typing the <tt>:Test</tt> command. To set that up, just include <tt>~/svn/devscripts/vim/include.vim</tt> .
|
@@ -0,0 +1,4 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/kernel/require_all"
|
2
|
+
require_all File.dirname(__FILE__),
|
3
|
+
:exclude => /(^|\/)test\//, # Don't include anything in test/ because those files will include test/unit, which causes tests to automatically be run (an unfortunate side-effect)!
|
4
|
+
:exclude_files => 'all.rb'
|
@@ -0,0 +1,44 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Tyler Rick
|
3
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
4
|
+
# License:: Ruby License
|
5
|
+
# Submit to Facets?:: Yes.
|
6
|
+
# Wait, so Facets has mode (http://facets.rubyforge.org/src/doc/rdoc/core/classes/Enumerable.html#M001253) but it doesn't have mean/average?
|
7
|
+
# Whether or not this Array#average is included, Facets ought to have an Enumerable#mean/average similar to mode that uses each iterator rather than Array#size. (Still might want to keep this version if it's more efficient for Arrays?)
|
8
|
+
#++
|
9
|
+
|
10
|
+
class Array
|
11
|
+
# Calculates the arithmetic average (mean) of the elements in the array as a <tt>Float</tt>.
|
12
|
+
# irb -> [1, 3, 3].average
|
13
|
+
# => 2.33333333333333
|
14
|
+
def average
|
15
|
+
if self.size == 0
|
16
|
+
raise ZeroDivisionError
|
17
|
+
end
|
18
|
+
self.inject(0.0) do |sum, item|
|
19
|
+
sum + item.to_f
|
20
|
+
end / self.size
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# _____ _
|
25
|
+
# |_ _|__ ___| |_
|
26
|
+
# | |/ _ \/ __| __|
|
27
|
+
# | | __/\__ \ |_
|
28
|
+
# |_|\___||___/\__|
|
29
|
+
#
|
30
|
+
=begin test
|
31
|
+
require 'test/unit'
|
32
|
+
class TheTest < Test::Unit::TestCase
|
33
|
+
def test_average
|
34
|
+
assert_equal 2, [0, 4].average
|
35
|
+
assert_equal Float, [0, 4].average.class
|
36
|
+
|
37
|
+
assert_equal 2.5, [0, 5].average
|
38
|
+
|
39
|
+
assert_raise ZeroDivisionError do
|
40
|
+
[].average
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
=end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Tyler Rick
|
3
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
4
|
+
# License:: Ruby License
|
5
|
+
# Submit to Facets?:: Yes!
|
6
|
+
# Developer notes:
|
7
|
+
# * This is the analog in Array to Set#classify (core).
|
8
|
+
# * Compare to Array#group_by (qualitysmith_extensions), which assumes all elements are arrays (making a "table") and only
|
9
|
+
# allows you to do simple classification by the value of a "column". On the other hand, it adds the option to delete that
|
10
|
+
# column from the array, which can be nice, since the classification key in the hash makes it somewhat redundant.
|
11
|
+
#++
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
gem 'facets'
|
15
|
+
require 'facet/array/to_hash'
|
16
|
+
class Array
|
17
|
+
|
18
|
+
=begin rdoc
|
19
|
+
Classifies the array by the return value of the given block and returns a hash of {value => array of elements} pairs.
|
20
|
+
The block is called once for each element of the array, passing the element as parameter.
|
21
|
+
|
22
|
+
Breaks an array into a hash of smaller arrays, making a new group for each unique value returned by the block. Each unique value becomes a key in the hash.
|
23
|
+
|
24
|
+
Example:
|
25
|
+
[
|
26
|
+
['a', 1],
|
27
|
+
['a', 2],
|
28
|
+
['b', 3],
|
29
|
+
['b', 4],
|
30
|
+
].classify {|o| o[0]}
|
31
|
+
=>
|
32
|
+
{
|
33
|
+
"a" => [['a', 1], ['a', 2]],
|
34
|
+
"b" => [['b', 3], ['b', 4]]
|
35
|
+
}
|
36
|
+
=end
|
37
|
+
def classify(&block)
|
38
|
+
hash = {}
|
39
|
+
each do |element|
|
40
|
+
classification = yield(element)
|
41
|
+
(hash[classification] ||= []) << element
|
42
|
+
end
|
43
|
+
hash
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# _____ _
|
48
|
+
# |_ _|__ ___| |_
|
49
|
+
# | |/ _ \/ __| __|
|
50
|
+
# | | __/\__ \ |_
|
51
|
+
# |_|\___||___/\__|
|
52
|
+
#
|
53
|
+
=begin test
|
54
|
+
require 'set'
|
55
|
+
|
56
|
+
class TheTest < Test::Unit::TestCase
|
57
|
+
def test_classify
|
58
|
+
input = [
|
59
|
+
['a', 1],
|
60
|
+
['a', 2],
|
61
|
+
['b', 3],
|
62
|
+
['b', 4],
|
63
|
+
]
|
64
|
+
assert_equal({
|
65
|
+
"a" => [['a', 1], ['a', 2]],
|
66
|
+
"b" => [['b', 3], ['b', 4]]
|
67
|
+
}, input.classify {|o| o[0]}
|
68
|
+
)
|
69
|
+
# For comparison:
|
70
|
+
assert_equal({
|
71
|
+
"a" => Set[['a', 1], ['a', 2]],
|
72
|
+
"b" => Set[['b', 3], ['b', 4]]
|
73
|
+
}, input.to_set.classify {|o| o[0]}
|
74
|
+
)
|
75
|
+
|
76
|
+
|
77
|
+
input = [
|
78
|
+
['Bob', "Bottle of water", 1.00],
|
79
|
+
['Bob', "Expensive stapler", 50.00],
|
80
|
+
['Alice', "Dinner for 2", 100.00],
|
81
|
+
['Alice', "Bus ride to RubyConf", 50.00],
|
82
|
+
]
|
83
|
+
assert_equal({
|
84
|
+
"Alice" => [['Alice',"Dinner for 2", 100.0], ['Alice', "Bus ride to RubyConf", 50.0]],
|
85
|
+
"Bob" => [['Bob', "Bottle of water", 1.0], ['Bob', "Expensive stapler", 50.0]]
|
86
|
+
}, input.classify {|o| o[0]}
|
87
|
+
)
|
88
|
+
assert_equal({
|
89
|
+
50.0 => [["Bob", "Expensive stapler", 50.00], ["Alice", "Bus ride to RubyConf", 50.00]],
|
90
|
+
100.0 => [["Alice", "Dinner for 2", 100.00]],
|
91
|
+
1.0 => [["Bob", "Bottle of water", 1.00]]
|
92
|
+
}, input.classify {|o| o[2]}
|
93
|
+
)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
=end
|
97
|
+
|
@@ -0,0 +1,52 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Tyler Rick
|
3
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
4
|
+
# License:: Ruby License
|
5
|
+
# Submit to Facets?:: Yes.
|
6
|
+
#++
|
7
|
+
|
8
|
+
require 'rubygems'
|
9
|
+
require 'facets/core/kernel/silence_warnings'
|
10
|
+
|
11
|
+
class Array
|
12
|
+
# Expands (calls +to_a+ on) all Ranges contained in this array, replacing the range with the list of *elements* that the range represents.
|
13
|
+
#
|
14
|
+
# This is especially useful when you want to have "discontiguous ranges" like [1..3, 5..7]...
|
15
|
+
#
|
16
|
+
# [1..3, 5..7].expand_ranges
|
17
|
+
# => [1, 2, 3, 5, 6, 7]
|
18
|
+
#
|
19
|
+
def expand_ranges
|
20
|
+
new_array = []
|
21
|
+
each do |item|
|
22
|
+
silence_warnings do # Object.to_a: warning: default `to_a' will be obsolete
|
23
|
+
if item.respond_to?(:to_a)
|
24
|
+
new_array.concat item.to_a
|
25
|
+
else
|
26
|
+
new_array.concat [item]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
new_array
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# _____ _
|
35
|
+
# |_ _|__ ___| |_
|
36
|
+
# | |/ _ \/ __| __|
|
37
|
+
# | | __/\__ \ |_
|
38
|
+
# |_|\___||___/\__|
|
39
|
+
#
|
40
|
+
=begin test
|
41
|
+
require 'test/unit'
|
42
|
+
class TheTest < Test::Unit::TestCase
|
43
|
+
def test_1
|
44
|
+
assert_equal [1, 2, 3], [1, 2, 3].expand_ranges
|
45
|
+
end
|
46
|
+
def test_2
|
47
|
+
assert_equal [1, 2, 3], [1..3].expand_ranges
|
48
|
+
assert_equal [1, 2, 3, 5, 6, 7], [1..3, 5..7].expand_ranges
|
49
|
+
end
|
50
|
+
end
|
51
|
+
=end
|
52
|
+
|
@@ -0,0 +1,134 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Tyler Rick
|
3
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
4
|
+
# License:: Ruby License
|
5
|
+
# Submit to Facets?:: Maybe.
|
6
|
+
# Developer notes:
|
7
|
+
# * Name is too general? Name it something to do with 'tables'?
|
8
|
+
# * group_table_by ?
|
9
|
+
# * Compare to Array#classify (qualitysmith_extensions), which aims to be more general, letting you classify arrays that are
|
10
|
+
# *not* in "table" form (whose elements are *not* all arrays of equal size and might not even be *arrays*).
|
11
|
+
#++
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
gem 'facets'
|
15
|
+
require 'facet/array/delete_values_at'
|
16
|
+
class Array
|
17
|
+
|
18
|
+
=begin rdoc
|
19
|
+
Breaks an array into a hash of smaller arrays, making a new group for each unique value in the specified column.
|
20
|
+
Each unique value becomes a key in the hash.
|
21
|
+
|
22
|
+
Example:
|
23
|
+
[
|
24
|
+
['a', 1],
|
25
|
+
['a', 2],
|
26
|
+
['b', 3],
|
27
|
+
['b', 4],
|
28
|
+
].group_by(0)
|
29
|
+
=>
|
30
|
+
"a"=>[[1], [2]],
|
31
|
+
"b"=>[[3], [4]]
|
32
|
+
|
33
|
+
Options:
|
34
|
+
* <tt>delete_key</tt>: deletes the key from the corresponding array if true (default true)
|
35
|
+
|
36
|
+
Example:
|
37
|
+
[
|
38
|
+
['a', 1],
|
39
|
+
['a', 2],
|
40
|
+
['b', 3],
|
41
|
+
['b', 4],
|
42
|
+
].group_by(0, :delete_key => false)
|
43
|
+
=>
|
44
|
+
"a"=>[['a', 1], ['a', 2]],
|
45
|
+
"b"=>[['b', 3], ['b', 4]]
|
46
|
+
|
47
|
+
*Notes*:
|
48
|
+
* <tt>self</tt> must be in the shape of a "table" (that is, a rectangular-shaped, two-dimensional array = an array of arrays,
|
49
|
+
each member array being of the same size (the "width" of the table)).
|
50
|
+
* This is different from the GROUP BY in SQL in that it doesn't apply an aggregate (like sum or average) to each group -- it just returns each group unmodified.
|
51
|
+
|
52
|
+
=end
|
53
|
+
def group_by(column_index, *args)
|
54
|
+
options = (if args.last.is_a?(Hash) then args.pop else {} end)
|
55
|
+
hash = {}
|
56
|
+
self.each do |row|
|
57
|
+
row_to_keep = row.dup
|
58
|
+
row_to_keep.delete_values_at(column_index) unless options[:delete_key] == false
|
59
|
+
|
60
|
+
hash[row[column_index]] ||= []
|
61
|
+
hash[row[column_index]] << row_to_keep
|
62
|
+
end
|
63
|
+
hash
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# _____ _
|
68
|
+
# |_ _|__ ___| |_
|
69
|
+
# | |/ _ \/ __| __|
|
70
|
+
# | | __/\__ \ |_
|
71
|
+
# |_|\___||___/\__|
|
72
|
+
#
|
73
|
+
=begin test
|
74
|
+
require 'set'
|
75
|
+
|
76
|
+
class TheTest < Test::Unit::TestCase
|
77
|
+
def test_group_by
|
78
|
+
assert_equal({ }, [ ].group_by(column_index = 0))
|
79
|
+
|
80
|
+
assert_equal({
|
81
|
+
"a"=>[[1], [2]],
|
82
|
+
"b"=>[[3], [4]]
|
83
|
+
}, [
|
84
|
+
['a', 1],
|
85
|
+
['a', 2],
|
86
|
+
['b', 3],
|
87
|
+
['b', 4],
|
88
|
+
].group_by(column_index = 0)
|
89
|
+
)
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
assert_equal({
|
94
|
+
"a"=>[['a', 1], ['a', 2]],
|
95
|
+
"b"=>[['b', 3], ['b', 4]]
|
96
|
+
}, [
|
97
|
+
['a', 1],
|
98
|
+
['a', 2],
|
99
|
+
['b', 3],
|
100
|
+
['b', 4],
|
101
|
+
].group_by(column_index = 0, :delete_key => false)
|
102
|
+
)
|
103
|
+
assert_equal({
|
104
|
+
"a" => Set[['a', 1], ['a', 2]],
|
105
|
+
"b" => Set[['b', 3], ['b', 4]]
|
106
|
+
}, [
|
107
|
+
['a', 1],
|
108
|
+
['a', 2],
|
109
|
+
['b', 3],
|
110
|
+
['b', 4],
|
111
|
+
].to_set.classify {|o| o[0]}
|
112
|
+
)
|
113
|
+
|
114
|
+
|
115
|
+
input = [
|
116
|
+
['Bob', "Bottle of water", 1.00],
|
117
|
+
['Bob', "Expensive stapler", 50.00],
|
118
|
+
['Alice', "Dinner for 2", 100.00],
|
119
|
+
['Alice', "Bus ride to RubyConf", 50.00],
|
120
|
+
]
|
121
|
+
assert_equal({
|
122
|
+
"Alice"=>[["Dinner for 2", 100.0], ["Bus ride to RubyConf", 50.0]],
|
123
|
+
"Bob"=>[["Bottle of water", 1.0], ["Expensive stapler", 50.0]]
|
124
|
+
}, input.group_by(column_index = 0)
|
125
|
+
)
|
126
|
+
assert_equal({
|
127
|
+
50.0=>[["Bob", "Expensive stapler"], ["Alice", "Bus ride to RubyConf"]],
|
128
|
+
100.0=>[["Alice", "Dinner for 2"]],
|
129
|
+
1.0=>[["Bob", "Bottle of water"]]
|
130
|
+
}, input.group_by(column_index = 2)
|
131
|
+
)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
=end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Lance Ivy
|
3
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
4
|
+
# License:: Ruby License
|
5
|
+
# Submit to Facets?:: Not sure.
|
6
|
+
#++
|
7
|
+
|
8
|
+
class Array
|
9
|
+
=begin rdoc
|
10
|
+
Returns the value previous to the given value. The value previous to the first is the last. Returns nil if the given value is not in the array.
|
11
|
+
|
12
|
+
Example:
|
13
|
+
sequence = ['a', 'b', 'c']
|
14
|
+
sequence.before('a') => 'c'
|
15
|
+
sequence.before('b') => 'a'
|
16
|
+
sequence.before('c') => 'b'
|
17
|
+
sequence.before('d') => nil
|
18
|
+
=end
|
19
|
+
def before(value)
|
20
|
+
return nil unless include? value
|
21
|
+
self[(index(value).to_i - 1) % length]
|
22
|
+
end
|
23
|
+
|
24
|
+
=begin rdoc
|
25
|
+
Returns the value after the given value. The value before the last is the first. Returns nil if the given value is not in the array.
|
26
|
+
|
27
|
+
Example:
|
28
|
+
sequence = ['a', 'b', 'c']
|
29
|
+
sequence.after('a') => 'b'
|
30
|
+
sequence.after('b') => 'c'
|
31
|
+
sequence.after('c') => 'a'
|
32
|
+
sequence.after('d') => nil
|
33
|
+
=end
|
34
|
+
def after(value)
|
35
|
+
return nil unless include? value
|
36
|
+
self[(index(value).to_i + 1) % length]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# _____ _
|
41
|
+
# |_ _|__ ___| |_
|
42
|
+
# | |/ _ \/ __| __|
|
43
|
+
# | | __/\__ \ |_
|
44
|
+
# |_|\___||___/\__|
|
45
|
+
#
|
46
|
+
=begin test
|
47
|
+
class TheTest < Test::Unit::TestCase
|
48
|
+
def setup
|
49
|
+
@sequence = ['a', 'b', 'c']
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_before
|
53
|
+
assert_equal 'c', @sequence.before('a')
|
54
|
+
assert_equal 'a', @sequence.before('b')
|
55
|
+
assert_equal 'b', @sequence.before('c')
|
56
|
+
assert_equal nil, @sequence.before('d')
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_after
|
60
|
+
assert_equal 'b', @sequence.after('a')
|
61
|
+
assert_equal 'c', @sequence.after('b')
|
62
|
+
assert_equal 'a', @sequence.after('c')
|
63
|
+
assert_equal nil, @sequence.after('d')
|
64
|
+
end
|
65
|
+
end
|
66
|
+
=end
|