我正在努力让自定义排序工作。最终,我将尝试将其应用于数据库查询,但在此之前,我想证明逻辑在内存中排序。问题是,即使是最简单的排序方法也无法工作!
排序方法:
def self.sort!(reputation_alerts)
#reputation_alerts.sort { |a, b| b <=> a }
reputation_alerts.sort { |a, b| b.id <=> a.id }
end
我原本希望第一种排序(目前被注释掉)会以相反的顺序返回Reputation_alerts。它没有做任何事。
我原本希望第二种类型会以相反的顺序返回按ID排序的信誉警报。它没有做任何事。
我通过迭代返回的Reputation_alerts对象并转储每个对象的内容来测试排序;每次“排序”结果与原始订单相同......
测试方法:
test "ReputationAlertSort PassedArray SortsArrayCorrectly" do
@customer = customers(:one)
@customer.update(keywords: { 1 => "bob", 2 => "wibble", 3 => "random" } )
@customer.get_keywords
@customer.reputation_alerts.clear
@customer.reputation_alerts.build(
id: 2, rep_keyword: "random", search_engine: "bing", rank: 1)
@customer.reputation_alerts.build(
id: 1, rep_keyword: "wibble", search_engine: "google", rank: 2)
@customer.reputation_alerts.build(
id: 3, rep_keyword: "wibble", search_engine: "google", rank: 1)
@customer.reputation_alerts.build(
id: 4, rep_keyword: "wibble", search_engine: "yahoo", rank: 2)
@customer.reputation_alerts.build(
id: 5, rep_keyword: "wibble", search_engine: "yahoo", rank: 1)
@customer.reputation_alerts.build(
id: 6, rep_keyword: "bob", search_engine: "google", rank: 2)
@customer.reputation_alerts.build(
id: 7, rep_keyword: "bob", search_engine: "yahoo", rank: 1)
@customer.reputation_alerts.build(
id: 8, rep_keyword: "random", search_engine: "bing", rank: 2)
ReputationAlert.sort!(@customer.reputation_alerts)
assert_sorted(1, 7)
assert_sorted(2, 6)
assert_sorted(3, 5)
assert_sorted(4, 4)
assert_sorted(5, 3)
assert_sorted(6, 2)
assert_sorted(7, 1)
assert_sorted(8, 8)
end
def assert_sorted(post_sort_position, pre_sort_position)
assert_equal post_sort_position,
@customer.reputation_alerts[pre_sort_position - 1].id, dump
end
def dump
dump = ""
@customer.reputation_alerts.each do |a|
dump += "\n#{a.id}, #{a.rep_keyword}, #{a.search_engine}, #{a.rank}"
end
dump
end
有什么建议吗?一旦我能够完成这项工作,我就可以继续进行实际的(复杂的)排序......
编辑:
我认为我试图排序的对象类型可能会造成问题,所以我尝试了更基本的类型:
temp.sort
:
test "ReputationAlertSort PassedArray SortsArrayCorrectly" do
temp = 1..7
temp.sort { |a, b| b <=> a }
raise "#{temp}"
end
这返回temp仍未排序。 (由于缺少一种预期的种类!)
temp.sort!
test "ReputationAlertSort PassedArray SortsArrayCorrectly" do
temp = 1..7
temp.sort! { |a, b| b <=> a }
raise "#{temp}"
end
这给出了错误:NoMethodError:未定义的方法`sort!'对于1..7:范围
temp = temp.sort!
test "ReputationAlertSort PassedArray SortsArrayCorrectly" do
temp = 1..7
temp = temp.sort { |a, b| b <=> a }
raise "#{temp}"
end
这至少可以起作用,所以也许我可以用它作为起点来解决这个问题......
答案 0 :(得分:1)
您没有用您的排序覆盖Reputation_alerts对象。只需在排序中添加一个感叹号:
def self.sorting(models)
models.sort!{ |a, b| b.id <=> a.id }
end
Model.sorting(models).map(&:id)
=> [17,16,15...]
编辑:
哎呀,我没想到它自称。我确实尝试在我的模型中添加一个类似的方法,它似乎工作正常。reputation_alerts.sort! { |a, b| b.id <=> a.id }
另一方面,所有这些似乎都是多余的,因为.sort方法应该存在于Enumerable中的任何集合中。您应该只能致电models = models.sort{...}
。
EDIT2:
如果你没有排序!出于某种原因,只需在添加的问题信息中使用.sort:
Range("A1").Select
Selection.Copy
Range("B1").Select
ActiveSheet.Paste
这与排序相同!
答案 1 :(得分:1)
您的方法sort!
返回一个已排序的数组,但您没有对结果执行任何操作?命名似乎表明你进行了就地排序,但你的方法没有。因此,要么在方法中使用.sort!
,要么将方法重命名为sort
并存储结果并进行检查。
其次,您的编辑:temp
是一个范围,为了确保排序有效,您必须先将其转换为数组。所以,如果你写
temp = (1..7).to_a
它应该有用。
答案 2 :(得分:0)
其他答案确实有助于解决这个问题,但除此之外还有一些问题,所以这里有一个完整的解决方案:
1:.sort!
对我正在使用的集合不起作用。它是子元素的集合(特别是使用has_many关联)。试图致电.sort!
会出错:
NoMethodError: undefined method `sort!' for #<ReputationAlert::ActiveRecord_Associations_CollectionProxy:0x61729b0>
2:Owner.Collection = Owner.Collection.sort { <snip> }
无效。将集合的排序结果分配给原始集合本身会导致此实例中的未排序集合。我怀疑这可能是ActiveRecord协会特有的行为。
3:new_variable = Owner.Collection.sort { <snip> }
有效。获取排序结果并将其分配给其他任意变量并使用它得到所需(排序)的结果。
总之,这里的问题似乎不是排序功能本身,而是ActiveRecord关联的排序功能的具体问题。
(当然,这实际上可能是一个多余的问题,因为计划最终让ActiveRecord查询处理我们的排序......)