如何将块传递给我的 "bubble sort" 方法?
How can I pass in a block to my "bubble sort" method?
下面的代码是我的冒泡排序方法的新手。
#For each element in the list, look at that element and the element
#directly to it's right. Swap these two elements so they are in
#ascending order.
def bubble_sort (array)
a = 0
b = 1
until (array.each_cons(2).all? { |a, b| (a <=> b) <= 0}) == true do
sort = lambda {array[a] <=> array[b]}
sort_call = sort.call
loop do
case sort_call
when -1 #don't swap
a += 1
b += 1
break
when 0 #don't swap
a += 1
b += 1
break
when 1 #swap
array.insert(a,array.delete_at(b))
a += 1
b += 1
break
else #end of array, return to start
a = 0
b = 1
break
end
end
end
puts array.inspect
end
array = [4, 2, 5, 6, 3, 23, 5546, 234, 234, 6]
bubble_sort(array)
我希望能够更改此方法,使其将一段代码作为参数并使用它来确定其排序方式。
例如:
array = ["hello", "my", "name", "is", "daniel"]
bubble_sort(array) {array[@a].length <=> array[@b].length}
(当我尝试这个时,我在整个代码中将 a
和 b
变成了实例变量。)
我曾尝试使用 yield
,但一旦到达数组末尾,我就会得到 undefined method 'length' for nil:NilClass
。我试过添加
之类的东西
if array[@b+1] == nil
@a = 0
@b = 1
end
这有帮助,但我仍然遇到奇怪的问题,例如无限循环或无法对超过一定数量的元素进行排序。
长话短说,我已经在这里待了几个小时了。有没有一种简单的方法可以做我想做的事?谢谢。
你离得不远了。只是一些事情:
使您的函数采用块参数
def bubble_sort (array, &block)
检查用户是否提供了区块
if block_given?
# Call user's comparator block
else
# Use the default behavior
end
调用用户的比较器块
block.call(a, b)
在用户提供的块中,接受要比较的元素的块参数
bubble_sort(array) {|a,b| a.length <=> b.length}
这应该让您处于正确的范围内。
你调用 lambda 的方式有点奇怪。其实完全没有必要。我重构了您的代码并清理了一些冗余。以下对我有用:
def sorted?(arr)
arr.each_cons(2).all? { |a, b| (a <=> b) <= 0 }
end
def bubble_sort (arr)
a = 0
b = 1
until sorted?(arr) do
# The yield call here passes `arr[a]` and `arr[b]` to the block.
comparison = if block_given?
yield(arr[a], arr[b])
else
arr[a] <=> arr[b]
end
if [-1, 0, 1].include? comparison
arr.insert(a, arr.delete_at(b)) if comparison == 1
a += 1
b += 1
else
a = 0
b = 1
end
end
arr
end
sample_array = [4, 2, 5, 6, 3, 23, 5546, 234, 234, 6]
# Sanity check:
100.times do
# `a` is the value of `arr[a]` in our function above. Likewise for `b` and `arr[b]`.
print bubble_sort(sample_array.shuffle) { |a, b| a <=> b }, "\n"
end
编辑
更干净的版本:
# In place swap will be more efficient as it doesn't need to modify the size of the arra
def swap(arr, idx)
raise IndexError.new("Index #{idx} is out of bounds") if idx >= arr.length || idx < 0
temp = arr[idx]
arr[idx] = arr[idx + 1]
arr[idx + 1] = temp
end
def bubble_sort(arr)
loop do
sorted_elements = 0
arr.each_cons(2).each_with_index do |pair, idx|
comparison = if block_given?
yield pair.first, pair.last
else
pair.first <=> pair.last
end
if comparison > 0
swap(arr, idx)
else
sorted_elements += 1
end
end
return arr if sorted_elements >= arr.length - 1
end
end
# A simple test
sample_array = [4, 2, 2, 2, 2, 2, 5, 5, 6, 3, 23, 5546, 234, 234, 6]
sample_str_array = ["a", "ccc", "ccccc"]
100.times do
print bubble_sort(sample_array.shuffle) { |a, b| a <=> b }, "\n"
print bubble_sort(sample_str_array.shuffle) { |a, b| a.length <=> b.length }, "\n"
end
下面的代码是我的冒泡排序方法的新手。
#For each element in the list, look at that element and the element
#directly to it's right. Swap these two elements so they are in
#ascending order.
def bubble_sort (array)
a = 0
b = 1
until (array.each_cons(2).all? { |a, b| (a <=> b) <= 0}) == true do
sort = lambda {array[a] <=> array[b]}
sort_call = sort.call
loop do
case sort_call
when -1 #don't swap
a += 1
b += 1
break
when 0 #don't swap
a += 1
b += 1
break
when 1 #swap
array.insert(a,array.delete_at(b))
a += 1
b += 1
break
else #end of array, return to start
a = 0
b = 1
break
end
end
end
puts array.inspect
end
array = [4, 2, 5, 6, 3, 23, 5546, 234, 234, 6]
bubble_sort(array)
我希望能够更改此方法,使其将一段代码作为参数并使用它来确定其排序方式。
例如:
array = ["hello", "my", "name", "is", "daniel"]
bubble_sort(array) {array[@a].length <=> array[@b].length}
(当我尝试这个时,我在整个代码中将 a
和 b
变成了实例变量。)
我曾尝试使用 yield
,但一旦到达数组末尾,我就会得到 undefined method 'length' for nil:NilClass
。我试过添加
if array[@b+1] == nil
@a = 0
@b = 1
end
这有帮助,但我仍然遇到奇怪的问题,例如无限循环或无法对超过一定数量的元素进行排序。
长话短说,我已经在这里待了几个小时了。有没有一种简单的方法可以做我想做的事?谢谢。
你离得不远了。只是一些事情:
使您的函数采用块参数
def bubble_sort (array, &block)
检查用户是否提供了区块
if block_given? # Call user's comparator block else # Use the default behavior end
调用用户的比较器块
block.call(a, b)
在用户提供的块中,接受要比较的元素的块参数
bubble_sort(array) {|a,b| a.length <=> b.length}
这应该让您处于正确的范围内。
你调用 lambda 的方式有点奇怪。其实完全没有必要。我重构了您的代码并清理了一些冗余。以下对我有用:
def sorted?(arr)
arr.each_cons(2).all? { |a, b| (a <=> b) <= 0 }
end
def bubble_sort (arr)
a = 0
b = 1
until sorted?(arr) do
# The yield call here passes `arr[a]` and `arr[b]` to the block.
comparison = if block_given?
yield(arr[a], arr[b])
else
arr[a] <=> arr[b]
end
if [-1, 0, 1].include? comparison
arr.insert(a, arr.delete_at(b)) if comparison == 1
a += 1
b += 1
else
a = 0
b = 1
end
end
arr
end
sample_array = [4, 2, 5, 6, 3, 23, 5546, 234, 234, 6]
# Sanity check:
100.times do
# `a` is the value of `arr[a]` in our function above. Likewise for `b` and `arr[b]`.
print bubble_sort(sample_array.shuffle) { |a, b| a <=> b }, "\n"
end
编辑
更干净的版本:
# In place swap will be more efficient as it doesn't need to modify the size of the arra
def swap(arr, idx)
raise IndexError.new("Index #{idx} is out of bounds") if idx >= arr.length || idx < 0
temp = arr[idx]
arr[idx] = arr[idx + 1]
arr[idx + 1] = temp
end
def bubble_sort(arr)
loop do
sorted_elements = 0
arr.each_cons(2).each_with_index do |pair, idx|
comparison = if block_given?
yield pair.first, pair.last
else
pair.first <=> pair.last
end
if comparison > 0
swap(arr, idx)
else
sorted_elements += 1
end
end
return arr if sorted_elements >= arr.length - 1
end
end
# A simple test
sample_array = [4, 2, 2, 2, 2, 2, 5, 5, 6, 3, 23, 5546, 234, 234, 6]
sample_str_array = ["a", "ccc", "ccccc"]
100.times do
print bubble_sort(sample_array.shuffle) { |a, b| a <=> b }, "\n"
print bubble_sort(sample_str_array.shuffle) { |a, b| a.length <=> b.length }, "\n"
end