如何选择每个区块中的项目?

时间:2014-09-10 07:31:52

标签: ruby arrays

如何选择each区块中的项目?或者,以相反的方式考虑它,如何修改select块内的项目?

作为一个例子,给定一个整数数组,我如何拒绝奇数,返回偶数数组,同时加10?在以下示例中,我希望返回[12, 14, 16]

尝试select

a = (1..6).to_a
a.select! do |i|
  if i % 2 == 0
    a[a.find_index(i)] += 10 # This doesn't stick.
    true # this works
  end
end
p a # => [2, 4, 6]

尝试each

a = (1..6).to_a
a.each do |i|
  if i % 2 == 0
    a[a.find_index(i)] += 10
  else
    a.delete(a.find_index(i)) # I suppose this isn't working?
  end
end
p a # => [1, 12, 3, 14, 5, 16]

5 个答案:

答案 0 :(得分:2)

您可以使用select删除所有奇数,并使用map执行所需的其他操作:

a.select { |x| x % 2 == 0 }.map { |x| x + 10 }
=> [12, 14, 16]

答案 1 :(得分:1)

使用map!转换数组的成员 - 而不是在数组中设置新值,只需返回您希望新值来自块的内容。对于您要拒绝的值,请返回nil

a = (1..6).to_a
a.map! do|i|
  if i % 2 == 0
    i + 10
  end
end.compact!
p a # => [12, 14, 16] 

更新

由于多次传递的问题很多,这里有一个flat_map的单程解决方案:

a = (1..6).to_a
a = a.flat_map do|i|
  if i.even? #happy?
    [i + 10]
  else
    []
  end
end
p a # => [12, 14, 16] 

可悲的是,没有flat_map!所以我们必须重新分配a

答案 2 :(得分:1)

作为好奇心,你也可以在Ruby> = 2中使用Ruby的懒惰枚举。

mega_range = (1..100_000)

filtered_collection = mega_range.lazy.select do |n|
    puts "selecting #{n}"
    n.even?
end.map do |n|
    puts "mapping #{n}"
    n * 2
end

filtered_collection.take(10).to_a

# selecting 1
# selecting 2
# mapping 2
# selecting 3
# selecting 4
# mapping 4
# selecting 5
# selecting 6
# mapping 6
# selecting 7
# selecting 8
# mapping 8
#  => [4, 8, 12, 16]

如您所见,selectmap操作已合并,map仅在所选事件上完成。

无需额外通过集合(这是compact!所做的)。

答案 3 :(得分:1)

我认为仅使用select无法修改任何元素,无法实现目标。

以下是其他替代方案(可能与上面的一些答案重复):

ary = (1..6).to_a

ary.map! { |x| x.even? ? x + 10 : nil }.compact!
ary.keep_if { |x| x.even? }.map! { |x| x + 10 }
ary.delete_if { |x| x.odd? }.map! { |x| x + 10 }
ary = ary.inject([]) { |final, element| element.even? ? final.push(element + 10) : final }

p ary # => [12, 14, 16]

答案 4 :(得分:0)

试试这个:

>> (1..6).select(&:even?).map { |x| x + 10 }
=> [12, 14, 16]