【问题标题】:In Rails, how do I figure out if an array of objects contains specific attributes matching given values?在 Rails 中,如何确定对象数组是否包含与给定值匹配的特定属性?
【发布时间】:2017-07-11 22:28:15
【问题描述】:

我正在使用 Ruby on Rails 5.0.1 和 Ruby 2.4。我有一个对象数组,存储在数组中,“结果”。每个对象都有一个数字属性

numeric_attr

我想知道,给定我的数组,我如何判断我是否只有一个对象,其数值属性值为“1”并递增一。顺序并不重要。因此,例如,如果我有一个包含三个对象的数组,

[MyObject(numeric_attr = 2), MyObject(numeric_attr = 1), MyObject(numeric_attr = 3)]

我想知道我是否恰好有一个 numeric_attr = 1 的对象、另一个 numeric_attr = 2 的对象和另一个 numeric_attr = 3 的对象。所以以上满足条件。下面的例子没有

[MyObject(numeric_attr = 4), MyObject(numeric_attr = 1), MyObject(numeric_attr = 3)]

因为虽然存在 numeric_attr = 1 的对象,但没有 numeric_attr = 2 的对象。 numeric_attr 字段可能为 nil。我该如何解决这个问题?

【问题讨论】:

    标签: ruby-on-rails arrays model attributes ruby-on-rails-5


    【解决方案1】:

    这个单行应该可以工作:

    results.map(&:numeric_attr).sort == (1..results.count).to_a
    

    说明:

    results
    #=> [#<MyObject:... @attr=2>, #<MyObject:... @attr=3>, #<MyObject:... @attr=1>]
    
    results.map(&:attr)
    #=> [2, 3, 1]
    
    results.map(&:attr).sort
    #=> [1, 2, 3]
    
    (1..results.length).to_a
    #=> [1, 2, 3]
    
    # therefore:
    results.map(&:attr).sort == (1..results.count).to_a
    #=> true
    

    如果numeric_attr 有可能是nil

    results.map(&:attr).compact.sort == (1..results.count).to_a
    

    当然,即使有一个nil值,结果也保证是false

    如果序列可以从任意数字开始,而不仅仅是 1:

    results.map(&:attr).sort == results.count.times.to_a.
      map { |i| i + results.map(&:attr).sort.first }
    

    但这不是很有效,因为它对数字进行了两次排序。

    【讨论】:

    • 不错。你怎么看类似的东西:((1..results.count).to_a-results.map(&amp;:numeric_attr)).empty?
    • 我也喜欢。更短:!(results.map(&amp;:numeric_attr)-(1..results.size).to_a).any?
    • 短一点:!(results.map(&amp;:attr)-a=*(1..results.size)).any?
    • 这给了我一个语法错误(Ruby 2.3.3)。然而,这不会:!(results.map(&amp;:attr)-(a=*(1..results.size))).any?
    • 你一开始就想出了减法,所以我们称之为偶数:)
    【解决方案2】:

    如果他们总是从 1 @Máté 的解决方案开始,如果他们可以从任意数字开始,那么你可以:

    count = 0
    array_objects.sort_by(&:numeric_attr).each_cons(2) {|a,b| count+=1 if a.numeric_attr==b.numeric_attr-1 }
    count+1==array_objects.count
    

    没有那么优雅,但可以处理更多情况

    【讨论】:

      猜你喜欢
      • 2012-01-03
      • 1970-01-01
      • 2010-11-10
      • 2021-11-16
      • 1970-01-01
      相关资源
      最近更新 更多