a map-like method that prevents elements from being included from the beginning when nil returns as a result

Asked 2 years ago, Updated 2 years ago, 44 views

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.

ruby

2022-09-30 18:58

4 Answers

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)?


2022-09-30 18:58

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


2022-09-30 18:58

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.


2022-09-30 18:58

[3,5,9].map {|x|x*x if x%3==0}.compact

Will this not work?


2022-09-30 18:58

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.