Ruby on rails 在Rails中,如何判断对象数组是否包含与给定值匹配的特定属性?

Ruby on rails 在Rails中,如何判断对象数组是否包含与给定值匹配的特定属性?,ruby-on-rails,arrays,model,attributes,ruby-on-rails-5,Ruby On Rails,Arrays,Model,Attributes,Ruby On Rails 5,我正在使用RubyonRails5.0.1和Ruby2.4。我有一个对象数组,存储在数组“results”中。每个对象都有一个数值属性 numeric_attr 我想知道,在给定数组的情况下,如何判断是否只有一个对象的数值属性值为“1”并递增1。秩序并不重要。例如,如果我有一个由三个对象组成的数组 [MyObject(numeric_attr = 2), MyObject(numeric_attr = 1), MyObject(numeric_attr = 3)] 我想知道是否有一个对象的数

我正在使用RubyonRails5.0.1和Ruby2.4。我有一个对象数组,存储在数组“results”中。每个对象都有一个数值属性

numeric_attr
我想知道,在给定数组的情况下,如何判断是否只有一个对象的数值属性值为“1”并递增1。秩序并不重要。例如,如果我有一个由三个对象组成的数组

[MyObject(numeric_attr = 2), MyObject(numeric_attr = 1), MyObject(numeric_attr = 3)]
我想知道是否有一个对象的数值为1,另一个对象的数值为2,另一个对象的数值为3。因此,上述条件满足。下面的示例不适用

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

因为尽管有一个数值为1的对象,但没有数值为2的对象。数值属性字段可能为零。我怎么才能知道呢?

这一行应该可以用:

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
results.map(&:attr).compact.sort == (1..results.count).to_a
results.map(&:attr).sort == results.count.times.to_a.
  map { |i| i + results.map(&:attr).sort.first }
说明:

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
results.map(&:attr).compact.sort == (1..results.count).to_a
results.map(&:attr).sort == results.count.times.to_a.
  map { |i| i + results.map(&:attr).sort.first }
当然,如果有一个
nil
值,那么结果肯定是
false

如果序列可以从任意数字开始,而不仅仅是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
results.map(&:attr).compact.sort == (1..results.count).to_a
results.map(&:attr).sort == results.count.times.to_a.
  map { |i| i + results.map(&:attr).sort.first }

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

如果它们总是从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

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

很好。你怎么看:
((1..results.count).to_a-results.map(&:numeric_attr)).empty?
我也喜欢这样。甚至更短:
!(results.map(&:numeric\u attr)-(1..results.size).to\u a).any?
更短:
!(results.map(&:attr)-a=*(1..results.size)).any?
这给了我一个语法错误(Ruby 2.3.3)。然而,这并不是:
!(results.map(&:attr)-(a=*(1..results.size)))。有吗?
您首先提出了一个减法,所以我们称之为偶数:)