For example, in an array, you want to create a new array in which the elements are multiplied only when they are multiples of 3.Specifically, if an array of [3,5,9]
is given, the expected result array is [9,81]
.To achieve this decision, you can use the following code:
[3,5,9].map { | x | x * x if x %3 == 0}.select { | x | !! x }
or:
[3,5,9].select {|x|x%3==0}.map {|x|x*x}
and so on.
Yes, it is possible to write like above, but personally, I would like to express in map
that if the return result is nil
, I don't want to include it in the array element without using select
.I'm thinking of writing something similar to the following:
[3,5,9].map { | x | x * x if x %3 == 0 }
Of course, if things go on like this, nil
elements will also be included, so we will not be able to achieve the above wishes.Please let me know if there are any methods or methods that can help me achieve my wishes.
map
is a one-to-one mapping, so I think it will be difficult to reduce the number of elements.
[3,5,9].map {|x|x*x if x%3==0}.compact#Map and remove nil
[3,5,9].inject([]){|ary, x|ary<<x*x if x%3==0;ary}#convolution
What do you think (although there are others)?
How about defining the filter_map
mentioned in the singleton methodEnumerator::Lazy.new example?
moduleEnumerable
def filter_map (&block)
map(&block).compact
end
end
class Enumerator::Lazy
def filter_map
Lazy.new(self)do|yelder, *values|
result=yield*values
yelder<<result if result
end
end
end
(1..Float::INFINITY).lazy.filter_map {|i|i*if i.even?}.first (5)
# => [4,16,36,64,100]
Incidentally, Ruby's bug tracking system has issued a Feature Request for a method similar to this question.
If you have a name for a good method, you will be able to use it in Ruby, so why don't you comment on issue?
Feature#5663: Combined map/select method-Ruby trunk-Ruby Issue Tracking System
If you want that method, you can create it once you define it in the Enumerable module.
moduleEnumerable
defmap_without_nil
self.inject([])do|arr,item|
ret=yield item
arr<<retless ret.nil?
arr
end
end
end
[3,5,9].map_without_nil { | i | i * if i %3 == 0}# = > [9,81]
However, I don't recommend it because it's obviously less readable than using select
.
[3,5,9].map {|x|x*x if x%3==0}.compact
Will this not work?
© 2024 OneMinuteCode. All rights reserved.