优化这个红宝石循环结构

时间:2017-01-26 22:09:08

标签: ruby loops

给定事实列表,测试事实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

更多

3 个答案:

答案 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_factsalternative_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来提高效率。

相关问题