Ruby:如何将变量设置为0,或者如果已经设置,则增加1

时间:2009-09-02 18:28:12

标签: ruby arrays

我知道|| =运算符,但不认为它会帮助我...尝试创建一个数组来计算对象数组中“类型”的数量。

array.each do |c|
  newarray[c.type] = newarray[c.type] ? newarray[c.type]+1 ? 0
end

有更优雅的方法吗?

6 个答案:

答案 0 :(得分:15)

types = Hash.new(-1) # It feels like this should be 0, but to be
                     # equivalent to your example it needs to be -1
array.each do |c|
  types[c.type] += 1
end

答案 1 :(得分:6)

如果索引不存在,请使用Array#fetch方法为其提供默认值:

array.each do |c|
  newarray[c.type] = newarray.fetch(c.type, -1) + 1
end

答案 2 :(得分:4)

array.each do |c|
  newarray[c.type] = 1 + (newarray[c.type] || -1)
end

可选地

array.each do |c|
  newarray[c.type] ||= -1
  newarray[c.type] += 1
end

答案 3 :(得分:2)

||=确实有帮助:

types = {}
array.each do |c|
    types[c.class] ||= 0
    types[c.class] += 1
end

答案 4 :(得分:0)

您的变量newarray名称很奇怪,因为在Ruby和大多数其他语言中,数组是由整数索引的,而不是像Class这样的随机对象。这更有可能是Hash

此外,您应该使用c.class,而不是c.type,这已被弃用。

最后,由于您正在创建Hash,因此您可以像inject那样使用:{/ p>

newarray = array.inject( {} ) do |h,c|
  h[c.class] = h.key?(c.class) ? h[c.class]+1 : 0
  h
end

或者,对于单行:

newarray = array.inject( {} ) { |h,c| h[c.class] = h.key?(c.class) ? h[c.class]+1 : 0 ; h }

如您所见,这会产生预期效果:

irb(main):001:0> array = [1, {}, 42, [], Object.new(), [1, 2, 3]]
=> [1, {}, 42, [], #<Object:0x287030>, [1, 2, 3]]
irb(main):002:0> newarray = array.inject( {} ) { |h,c| h[c.class] = h.key?(c.class) ? h[c.class]+1 : 0 ; h }
=> {Object=>0, Hash=>0, Array=>1, Fixnum=>1}

答案 5 :(得分:0)

在Ruby 1.8.7或更高版本中,您可以使用group_by然后将每个元素列表转换为count - 1,并从map返回的数组中创建一个哈希值。

Hash[array.group_by(&:class).map { |k,v| [k, v.size-1] }]