使用.min和max并推送到数组

时间:2015-03-27 03:28:07

标签: ruby arrays sorting

我正在通过克里斯·派恩的学习"学习编程"我正在参考第10章的练习,他要求你在不使用.sort的情况下按字母顺序排列单词列表。我使用了min / max(他可能并不打算使用它,但它是一个开始)。这是有效的,除非我使用.min并将该值推送到排序数组,结果是z到a,而不是像我预期的那样到z。当我使用max(我在下面的代码中使用它只是为了使它工作)时,它出现了a到z。知道为什么吗?

puts "Enter a list of words, separated by commas. Hit enter when done."
puts "This program will sort your words alphabetically."
word_list = gets.chomp.downcase

word_array = word_list.split(", ")

def sort_words (words)

    sorted_array = [] if sorted_array.nil?
    words = [] if words.nil?

    until words.length == 0
        first_word = words.max #method should be .min (?)
        words.delete(first_word)
        sorted_array.push(first_word) 
        sort_words(words)
    end

    puts sorted_array
end

sort_words(word_array)

2 个答案:

答案 0 :(得分:2)

这样想。

unsorted = [1, 3, 2, 5, 4]
sorted   = []

unsorted.max是5.删除它并将其推送到已排序。

unsorted = [1, 3, 2, 4]
sorted   = [5]

unsorted.max是4.删除它并将其推送到已排序。

unsorted = [1, 3, 2]
sorted   = [5, 4]

我想你可以看出错误所在。 push添加到数组的末尾,因此您希望从最小到最大构建sorted。因此使用unsorted.max

代码的问题是在删除最大值后在循环内调用sort_words(words)。这是recursion的一种形式。虽然您可以使用递归编写此排序例程,但将循环与递归混合会导致您的问题。

正在发生的事情是循环正在删除max元素,然后再次使用相同的列表减去max元素再次调用sort_words。然后它又一次又一次地再次这样做。你结束了一堆像...这样的电话。

   call_stack               sorted_array (local to each call)
sort_words([1,3,2,5,4])     [5]
sort_words([1,3,2,4])       [4]
sort_words([1,3,2])         [3]
sort_words([1,2])           [2]
sort_words([1])             [1]
sort_words([])              []

由于words是引用,因此不会在每次调用中复制它,因此对sort_words的每次调用都在同一个单词列表中进行。每次调用都会将words缩小一个。当words为空时,所有循环都会退出并打印其结果,但堆栈首先从底部返回!你得到的是什么

1
2
3
4
5

但如果您将puts sorted_array更改为puts "sorted array: #{sorted_array}",您会看到实际发生的事情。

sorted array: []
sorted array: ["1"]
sorted array: ["2"]
sorted array: ["3"]
sorted array: ["4"]
sorted array: ["5"]

答案 1 :(得分:0)

知道了,谢谢。用循环中的递归来覆盖它。删除了循环内对方法的调用。还将已排序的数组转换为字符串以进行输出。

puts "Enter a list of words, separated by commas. Hit enter when done."
puts "This program will sort your words alphabetically."
word_list = gets.chomp.downcase
word_array = word_list.split(", ")

def sort_words (words)

    sorted_array = [] if sorted_array.nil?
    words = [] if words.nil?

    until words.length == 0
        first_word = words.min
        words.delete(first_word)
        sorted_array.push(first_word) 
    end

        sorted_words = sorted_array.join(", ")
        puts sorted_words
end

sort_words(word_array)