This page contains automated test results for code from O'Reilly's Ruby Cookbook. If this code looks interesting or useful, you might want to buy the whole book.
| Making Sure a Sorted Array Stays Sorted | ||
|---|---|---|
| Code | Expected | Actual |
class SortedArray < Array
def initialize(*args, &sort_by)
@sort_by = sort_by || Proc.new { |x,y| x <=> y }
super(*args)
sort! &sort_by
end
def insert(i, v)
# The next line could be further optimized to perform a
# binary search.
insert_before = index(find { |x| @sort_by.call(x, v) == 1 })
super(insert_before ? insert_before : -1, v)
end
def <<(v)
insert(0, v)
end
alias push <<
alias unshift <<
["collect!", "flatten!", "[]="].each do |method_name|
module_eval %{
def #{method_name}(*args)
super
sort! &@sort_by
end
}
end
def reverse!
#Do nothing; reversing the array would disorder it.
end
end
a = SortedArray.new([3,2,1]) |
[1, 2, 3] | [1, 2, 3] |
unsorted= ["b", "aa", "a", "cccc", "1", "zzzzz", "k", "z"] strings_by_alpha = SortedArray.new(unsorted) |
["1", "a", "aa", "b", "cccc", "k", "z", "zzzzz"] | ["1", "a", "aa", "b", "cccc", "k", "z", "zzzzz"] |
strings_by_length = SortedArray.new(unsorted) do |x,y| x.length <=> y.length end |
["b", "z", "a", "k", "1", "aa", "cccc", "zzzzz"] | ["b", "z", "a", "k", "1", "aa", "cccc", "zzzzz"] |
a << -1 |
[-1, 1, 2, 3] | [-1, 1, 2, 3] |
a << 1.5 |
[-1, 1, 1.5, 2, 3] | [-1, 1, 1.5, 2, 3] |
a.push(2.5) |
[-1, 1, 1.5, 2, 2.5, 3] | [-1, 1, 1.5, 2, 2.5, 3] |
a.unshift(1.6) |
[-1, 1, 1.5, 1.6, 2, 2.5, 3] | [-1, 1, 1.5, 1.6, 2, 2.5, 3] |
a = SortedArray.new([10, 6, 4, -4, 200, 100]) |
[-4, 4, 6, 10, 100, 200] | [-4, 4, 6, 10, 100, 200] |
a.collect! { |x| x * -1 } |
[-200, -100, -10, -6, -4, 4] | [-200, -100, -10, -6, -4, 4] |
a[3] = 25 a |
[-200, -100, -10, -4, 4, 25] | [-200, -100, -10, -4, 4, 25] |
a[1..2] = [6000, 10, 600, 6] a |
[-200, -4, 4, 6, 10, 25, 600, 6000] | [-200, -4, 4, 6, 10, 25, 600, 6000] |
class SortedArray
def []=(*args)
if args.size == 3
#e.g. "a[6,3] = [1,2,3]"
start, length, value = args
slice! Range.new(start, start+length, true)
(value.respond_to? :each) ? value.each { |x| self << x } : self << value
elsif args.size == 2
index, value = args
if index.is_a? Numeric
#e.g. "a[0] = 10" (the most common form of array assignment)
delete_at(index)
self << value
elsif index.is_a? Range
#e.g. "a[0..3] = [1,2,3]"
slice! index
(value.respond_to? :each) ? value.each { |x| self << x } : self << value
else
#Not supported. Delegate to superclass; will probably give an error.
super
sort!(&sort_by)
end
else
#Not supported. Delegate to superclass; will probably give an error.
super
sort!(&sort_by)
end
end
end
a = SortedArray.new([1,2,3,4,5,6])
a[0] = 10
a |
[2, 3, 4, 5, 6, 10] | [2, 3, 4, 5, 6, 10] |
a[0, 2] = [100, 200] a |
[4, 5, 6, 10, 100, 200] | [4, 5, 6, 10, 100, 200] |
a[1..2] = [-4, 6] a |
[-4, 4, 6, 10, 100, 200] | [-4, 4, 6, 10, 100, 200] |
stripes = SortedArray.new(["aardwolf", "zebrafish"]) stripes[1].upcase! stripes |
["aardwolf", "ZEBRAFISH"] | ["aardwolf", "ZEBRAFISH"] |
stripes.sort! |
["ZEBRAFISH", "aardwolf"] | ["ZEBRAFISH", "aardwolf"] |
class Object
def to_frozen
f = self
unless frozen?
begin
f = dup.freeze
rescue TypeError
#This object can't be duped (e.g. Fixnum); fortunately,
#it usually can't be modified either
end
end
return f
end
end
class FrozenCopySortedArray < SortedArray
def insert(i, v)
insert_before = index(find { |x| x > v })
super(insert_before ? insert_before : -1, v.to_frozen)
end
["initialize", "collect!", "flatten!"].each do |method_name|
define_method(method_name) do
super
each_with_index { |x, i| self[i] = x.to_frozen }
# No need to sort; by doing an assignment to every element
# in the array, we've made #insert keep the array sorted.
end
end
end
stripes = SortedArray.new(["aardwolf", "zebrafish"])
stripes[1].upcase! |
TypeError: can't modify frozen string |
|
[1, "string"].sort |
ArgumentError: comparison of Fixnum with String failed ... |
ArgumentError: comparison of Fixnum with String failed from (irb):116:in `sort' from (irb):116 from :0 |
a = SortedArray.new([1]) a << "string" |
ArgumentError: comparison of Fixnum with String failed |
|
a = SortedArray.new([3, 2, 1]) |
[1, 2, 3] | [1, 2, 3] |
a += [1, -10] |
[1, 2, 3, 1, -10] | [1, 2, 3, 1, -10] |
a.class |
Array | Array |
class SortedArray
def + (other_array)
SortedArray.new(super)
end
end |
nil | |