迭代序列并一次更改一个对象的最佳方法(Ruby)

迭代序列并一次更改一个对象的最佳方法(Ruby),ruby,Ruby,我是ruby新手,觉得我仍然用C语言的夏普风格做很多事情:-)。 假设您有一个对象数组(问题:has_many=>:答案)。 我想迭代所有答案,如果一些答案符合条件,则更改答案属性。 目前,我的工作如下: def iterate_and_do_stuff for (a in self.answers) if(a.somecriteria==true) a.some_attr=some_val end end end 还有什么其他方法可以做到

我是ruby新手,觉得我仍然用C语言的夏普风格做很多事情:-)。 假设您有一个对象数组(问题:has_many=>:答案)。 我想迭代所有答案,如果一些答案符合条件,则更改答案属性。 目前,我的工作如下:

def iterate_and_do_stuff
   for (a in self.answers)
      if(a.somecriteria==true)
         a.some_attr=some_val
      end
   end
end
还有什么其他方法可以做到这一点?块、环等

请再见

谢谢。

使用:


self.answers.each{a | a.some_attr=some_val if a.some_criteria}

只是为了好玩一个选择

self.answers.select{|a| a.some_criteria}.each{|a| a.some_attr = some_val}


不过,这两种方法的效率都不如您的原始代码。

我更喜欢map!或收集!在这种情况下,因为您可以使用!方法在语义上表示正在就地更改数组

self.answers.map!{ |a| 
   a.some_criteria ? (a.some_attr = some_val) : a.some_attr  
}


通过这种方式,很明显您打算更改阵列。

如果您使用的是ActiveRecord模型,请不要忘记,您可以在数据库级别而不是内存中进行选择。换言之,您可以从数据库中只检索到要放入数组的值,然后只需更改这些值

下面是一个使用自定义查找器的示例(有点像以前的方法):

类问题{:已接受=>true}
结束
结束
结束
类答案
或者你也可以与其他协会合作:

class Question < ActiveRecord::Base
  has_many :answers
  has_many :accepted_answers, :class_name => "Answer", :conditions => { :accepted => true }
end

class Answer < ActiveRecord::Base
  belongs_to :question
end

q = Question.find :first
q.accepted_answers.each { |a| a.do_something! }
类问题“Answer”,:conditions=>{:接受的=>true}
结束
类答案
下面是另一个在子类上使用命名作用域(更新一点,在我看来是首选)的示例:

class Question < ActiveRecord::Base
  has_many :answers
end

class Answer < ActiveRecord::Base
  belongs_to :question
  named_scope :accepted, :conditions => { :accepted => true }
end

q = Question.find :first
q.answers.accepted.each { |a| a.do_something! }
类问题{:已接受=>true}
结束
q=问题。查找:首先
q、 答案。接受。每个{a{a}做点什么!}
但在任何情况下,您都抽象了“选择”,它有一些好处:

  • 在大型集合的情况下速度更快
  • 您已经将较低级别的选择标准抽象为具有较高级别语义的内容,这使您的代码更易于阅读和维护

  • 把这个转换成…结束挡块怎么样?比我快2分钟。他妈的必须查找文档。所以看起来总是像一场竞赛:-)它也将比使用#select后跟#each更有效,因为您只需在数组上迭代一次。
    self.answers.collect!{ |a| 
       a.some_criteria ? (a.some_attr = some_val) : a.some_attr
    }
    
    class Question < ActiveRecord::Base
      has_many :answers do
        def accepted
          find :all, :conditions => { :accepted => true }
        end
      end
    end
    
    class Answer < ActiveRecord::Base
      belongs_to :question
    end
    
    q = Question.find :first
    q.answers.accepted.each { |a| a.do_something! }
    
    class Question < ActiveRecord::Base
      has_many :answers
      has_many :accepted_answers, :class_name => "Answer", :conditions => { :accepted => true }
    end
    
    class Answer < ActiveRecord::Base
      belongs_to :question
    end
    
    q = Question.find :first
    q.accepted_answers.each { |a| a.do_something! }
    
    class Question < ActiveRecord::Base
      has_many :answers
    end
    
    class Answer < ActiveRecord::Base
      belongs_to :question
      named_scope :accepted, :conditions => { :accepted => true }
    end
    
    q = Question.find :first
    q.answers.accepted.each { |a| a.do_something! }