给定事实列表,测试事实class AbstractModule {
final void doSomething() {
String message = logMessage();
if (!message.isEmpty()) { System.out.println(message); }
}
String logMessage() { return ""; }
}
class Subclass extends AbstractModule {
@Override String logMessage() {
return "The message";
}
}
,如果is_real?
属性也没有说明alternative_facts,则仅返回passing_facts。
speaker
如何重新安排循环/测试,以便数据不必多次访问。
鉴于数据集的passing_facts, alternative_facts = []
@facts.each do |fact|
if fact.is_real?
passing_facts << fact
else
alternative_facts << fact
end
end
alternative_facts.each do |bad_fact|
passing_facts = passing_facts.reject {|good_fact| good_fact.speaker == bad_fact.speaker }
end
return passing_facts
比passing_facts
答案 0 :(得分:4)
您的前8行可以替换为Enumerable#partition
。
此代码在@facts
之后迭代一次,一次超过alternative_facts
,一次超过passing_facts
。它使用Set
来加快查找速度:
require 'set'
passing_facts, alternative_facts = @facts.partition(&:real?)
bad_speakers = Set.new(alternative_facts.map(&:speakers))
passing_facts.reject! do |fact|
bad_speakers.include? fact.speaker
end
return passing_facts
平均复杂度应为O(n)
,而代码为O(n**2)
,另一个答案为O(n*log(n))
。
答案 1 :(得分:3)
根据您将某种排序计为循环,这可能就足够了。
由于哈希访问很便宜,我们可以说它是O(1)
,排序是O(n*log(n))
。以下实现将O(n + n*log(n))
与O(n*log(n))
相同。这比您示例中的O(n + n^2)
〜O(n^2)
要少。
这也意味着访问数据的次数少于示例中的数据。
sorted_facts = @facts.sort_by(:real?).reverse!
author_invalidity = {}
sorted_facts.select do |fact|
author_invalidity[fact.speaker] ||= !fact.real?
fact.real? && !author_invalidity[fact.speaker]
end
对这个想法的快速解释。
我们尝试构建作者有效性的哈希映射,以从示例中删除嵌套循环。通过真实地对事实进行排序,以便将错误的事物排在第一位,我们可以保证,当我们迭代第一个真实事实时,我们在哈希映射中拥有所有无效的作者。然后通过检查哈希以及我们可以在同一次迭代中构建有效事实列表的事实,我们构建了哈希。
请注意,author_invalidity
和双!
令人困惑,但需要使用||=
。如果相反author_validity
将被存储(例如author_validity[fact.speaker] ||= fact.real?
),则在处理完第一个有效作者后,检查将始终返回true
。因此,逻辑必须是消极的。如其他答案中所述,可以使用Hash
而不是Set
。那么逻辑就是积极的。
希望这能让你思考正确的方向。
答案 2 :(得分:2)
我建议您按如下方式编写。
class Fact
def initialize (fact)
@fact = fact
end
def fact
@fact[:fact]
end
def is_real?
@fact[:real]
end
def speaker
@fact[:speaker]
end
end
创建一些实例。
facts = [["grass is green", true, "Bob"], ["bears are orange", false, "Sue"],
["cats say 'woof'", false, "Bob"], ["dogs are delightful", true, "Hal"]].
map { |f,t,s| Fact.new(fact: f, real: t, speaker: s) }
#=> [#<Fact:0x007fd363e4bcc0 @fact=
# {:fact=>"grass is green", :real=>true, :speaker=>"Bob"}>,
# #<Fact:0x007fd363e4bc20 @fact=
# {:fact=>"bears are orange", :real=>false, :speaker=>"Sue"}>,
# #<Fact:0x007fd363e4bb80 @fact=
# {:fact=>"cats say 'woof'", :real=>false, :speaker=>"Bob"}>,
# #<Fact:0x007fd363e4bae0 @fact=
# {:fact=>"dogs are delightful", :real=>true, :speaker=>"Sue"}>
# ]
将facts
分区为passing_facts
和alternative_facts
。
passing_facts, alternative_facts = facts.partition(&:is_real?)
#=> [[#<Fact:0x007fd363e4bcc0 @fact=
# {:fact=>"grass is green", :real=>true, :speaker=>"Bob"}>,
# #<Fact:0x007fd363e4bae0 @fact=
# {:fact=>"dogs are delightful", :real=>true, :speaker=>"Hal"}>
# ],
# [#<Fact:0x007fd363e4bc20 @fact=
# {:fact=>"bears are orange", :real=>false, :speaker=>"Sue"}>,
# #<Fact:0x007fd363e4bb80 @fact=
# {:fact=>"cats say 'woof'", :real=>false, :speaker=>"Bob"}>
# ]
# ]
passing_facts
#=> [#<Fact:0x007fd363e4bcc0 @fact=
# {:fact=>"grass is green", :real=>true, :speaker=>"Bob"}>,
# #<Fact:0x007fd363e4bae0 @fact=
# {:fact=>"dogs are delightful", :real=>true, :speaker=>"Hal"}>
# ]
alternative_facts
# [#<Fact:0x007fd363e4bc20 @fact=
# {:fact=>"bears are orange", :real=>false, :speaker=>"Sue"}>,
# #<Fact:0x007fd363e4bb80 @fact=
# {:fact=>"cats say 'woof'", :real=>false, :speaker=>"Bob"}>
# ]
编译alternative_facts
的发言人名单。
alternative_speakers = alternative_facts.map { |f| f.speaker }
#=> ["Sue", "Bob"]
拒绝passing_facts
的元素,其中:speaker
的键值是alternative_speakers
的成员,然后将剩余的元素映射到事实的名称。
passing_facts.reject { |f| alternative_speakers.include?(f.speaker) }.
map { |f| f.fact }
#=> ["dogs are delightful"]
请注意
passing_facts.reject { |f| alternative_speakers.include?(f.speaker) }
#=> [#<Fact:0x007fd364a38e70 @fact=
# {:fact=>"dogs are delightful", :real=>true, :speaker=>"Hal"}>
# ]
如果有大量的事实&#34;,可以通过在计算require 'set'
的表达式的末尾添加.to_set
并添加facts
来提高效率。