试图了解array.sort如何与自定义比较器块一起使用

时间:2013-12-03 21:48:41

标签: ruby

我是ruby的新手并且正在做RubyMonk教程。其中一个问题如下。有人可以赐教,因为我不理解建议的解决方案吗?

问题陈述 创建一个名为'sort_string'的方法,该方法接受一个String并按长度按升序重新排列所有单词。我们不要将标点符号与其他字符区别对待,并假设我们将始终使用单个空格来分隔单词。

示例:给定一个字符串“在一个句子中排序单词”,它应该返回“a in Sort words sentence”。

建议的解决方案:

def sort_string(string)
  string.split(' ').sort{|x, y| x.length <=> y.length}.join(' ')
end

我的问题是;

1)为什么有两个块变量通过?应该只有一个,因为你一次只能查看一个句子的每个元素吗?

2)我抬起了&lt; =&gt;运算符和它指出,“组合比较运算符。如果第一个操作数等于秒,则返回0,如果第一个操作数大于第二个,则返回1;如果第一个操作数小于第二个操作数,则返回-1。”那么我们不是基本上按-1,0和1排序,而不是单词?

非常感谢您的帮助!

4 个答案:

答案 0 :(得分:3)

1)为什么有两个块变量通过?应该只有一个,因为你一次只能查看一个句子的每一个元素吗?

因为这就是sort方法的工作原理。它一次比较两个元素,块告诉它如何比较两个元素。有一个名为sort_by的单元素方法,只需要一个可以在这种情况下使用的方法:

def sort_string(string)
  string.split(' ').sort_by{|x| x.length}.join(' ')
end

甚至更短:

def sort_string(string)
  string.split(' ').sort_by(&:length).join(' ')
end

2)我抬起了&lt; =&gt;运算符和它指出,“组合比较运算符。如果第一个操作数等于秒,则返回0,如果第一个操作数大于第二个,则返回1;如果第一个操作数小于第二个操作数,则返回-1。”那么我们不是基本上按-1,0和1排序,而不是单词?

同样,这就是排序的工作原理。排序查看结果,并根据值-101相应地对原始数据进行排序。它没有直接排序<=>的结果。如果您已完成任何C编程并使用strcmp,请考虑如何使用该函数。它基于相同的概念。

答案 1 :(得分:0)

对于第一个问题,如果你查看sort方法的文档,它的块形式有两个变量

http://www.ruby-doc.org/core-2.0.0/Array.html#method-i-sort

对于第二个问题,宇宙飞船运营商在两个操作数之间进行比较,然后返回-1,0或1,然后对结果进行排序。是的,您在-1,0和1上排序,但这些值是从比较中获得的。

答案 2 :(得分:0)

  1. 有两个块变量,因为要排序需要两个项目 - 你无法将一个项目与任何项目或自身进行比较。

  2. 您按-1,0和1排序 - 通过单词。

  3. 这两个问题都与排序方法有关 - 这是一个可以让它更清晰的例子:

    (1..10).sort { |a, b| b <=> a }  #=> [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
    

    对于每个数字1-10,sort查看'a'和'b' - 块参数。然后在块中,代码说要b高于a - 这就是它的作用

答案 3 :(得分:0)

默认情况下,sort功能按某种顺序对项目进行排序。

但是,如果传递一个块,它会使用该块比较数组的元素,以便您可以定义元素的不同自定义顺序。

也就是说,块必须比较元素。这种比较的简约工作版本是比较两个元素,只是为了知道哪一个是“大于或等于”。

这就是自定义块有两个参数的原因:这些是要比较的元素。你实际上并不知道哪一个。 sort将执行一些排序算法,并根据内部,它将选择一些元素对,使用您的块比较它们,然后,它将使用该知识按顺序重新排序元素。

当你提供一个'比较'的块时,返回BOOL的效果不是很高效。更好且通常更快一点的方法是确定元素是否相等,更少或更大。马上。

arr.sort {|item1, item2}
    if item1 < item2 return :lesser
    if item1 == item2 return :equal
    if item1 < item2 return :greater
}

这只是伪代码。

使用数字,很容易:只需减去它们。如果你得到小于零,你知道第一个是较小的。如果你得到的数字超过零,那么第一个就越大。如果你得零,他们是平等的。因此,在某种程度上,将“三方比较结果”描述为一些排序算法是“标准化”的方式。

arr.sort {|item1, item2}
    if item1 < item2 return -1
    if item1 == item2 return 0
    if item1 > item2 return 1
}

or just

arr.sort {|item1, item2}
    return item1 - item2
}

但并非所有类型都可以减去。 Ruby进一步发展并定义了“比较运算符”。它不是单独的</>/==/<=/>=,而是为您提供返回数值的<=>。 -1表示左边较小,依此类推。

arr.sort {|item1, item2}
    return item1 <=> item2
}

现在,如果您向<=>提供MyClass运算符,即使普通item1-item2无法使用非数字“MyClass”,您也可以轻松对其进行排序。 / p>