Project

General

Profile

Feature #15323

[PATCH] Proposal: Add Enumerable#filter_map

Added by alfonsojimenez (Alfonso Jiménez) 10 months ago. Updated 4 months ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:89907]

Description

This is a proposal for a combined filter + map method (https://bugs.ruby-lang.org/issues/5663).

This method both filters and maps the elements of an enumerable in just one iteration:

(1..10).filter_map { |i| i * 2 if i.even? } #=> [4, 8, 12, 16, 20]

GitHub PR: https://github.com/ruby/ruby/pull/2017


Files

0001-Adding-Enumerable-filter_map.patch (4.61 KB) 0001-Adding-Enumerable-filter_map.patch alfonsojimenez (Alfonso Jiménez), 04/25/2019 09:49 AM

Related issues

Related to Ruby master - Feature #5663: Combined map/select methodAssignedActions

Associated revisions

History

#1

Updated by alfonsojimenez (Alfonso Jiménez) 10 months ago

  • Description updated (diff)
#2

Updated by alfonsojimenez (Alfonso Jiménez) 10 months ago

  • File deleted (0001-Adding-Enumerable-filter_map.patch)
#3

Updated by alfonsojimenez (Alfonso Jiménez) 10 months ago

  • File 0001-Adding-Enumerable-filter_map.patch added

Updated by tny (Tony Sunny) 10 months ago

Could't we use reduce for this?

(1..10).reduce([]) { |a, i| i.even? ? a << (i * 2) : a }

Updated by shevegen (Robert A. Heiler) 10 months ago

I think the functionality, that is to combine .filter (be it select
or reject, is secondary to me), and .map, could be useful. I don't
really need it myself but I find it is not entirely out of the question
that others may find it useful.

There is, IMO, only one real drawback, if we ignore the functionality
aspect (where you'd have to ask matz anyway), and this is that I
think the two-word methods can be quite clumsy.

Not just .filter_map but also .yield_self, which eventually had an
alias called .then. If we ignore the question as to whether .then
is a good name (or .yield_self), one advantage that .then has
is that it is shorter.

Succinct expression is not always necessarily the best; but in this
case, I think single-word methods are very often better than two-word
methods.

.reduce() has, in my opinion, a slight other disadvantage, and that
is that people have to explicitely pass an , which is not always easy to remember. (For me it is hard
to remember because I rarely use .reduce either).

This is just my opinion, though. I do not really have any strong pro
or con way about the feature itself; only a very tiny dislike of
.filter_map as name. But it is not really a strong contra opinion
either way. (My biggest look ahead is on ruby's jit/mjit ... :D)

Updated by devpolish (Nardo Nykolyszyn) 9 months ago

(1..10).map { |e| e.even? ? (e * 2) : e }

Updated by oleynikov (Alexander Oleynikov) 9 months ago

nardonykolyszyn@gmail.com wrote:

(1..10).map { |e| e.even? ? (e * 2) : e }

Yeah, but without #filter this is still an array with 10 elements.

Updated by phluid61 (Matthew Kerwin) 9 months ago

tny (Tony Sunny) wrote:

Could't we use reduce for this?

(1..10).reduce([]) { |a, i| i.even? ? a << (i * 2) : a }

Yep, that's mentioned in the original ticket too. There's also #each_with_object that lets you write the block almost the same as in the proposal:

(1..10).each_with_object([]) { |i, a| a << i * 2 if i.even? }

The big difference here is you can capture nil/false values, because the filter test is explicitly separated from the map operation.

#9

Updated by shugo (Shugo Maeda) 7 months ago

Updated by shugo (Shugo Maeda) 7 months ago

+1 for filter_map.

Matz agreed the feature itself before: https://bugs.ruby-lang.org/issues/5663#note-42
The name filter_map is good because other languages have similar names (e.g., filter-map in Scheme).

#11

Updated by alfonsojimenez (Alfonso Jiménez) 5 months ago

  • File deleted (0001-Adding-Enumerable-filter_map.patch)

Updated by alfonsojimenez (Alfonso Jiménez) 5 months ago

I've updated the patch file increasing the ruby version in spec/ruby/core/enumerable/filter_map_spec.rb

Enumerable#filter_map was already accepted in the last developers meeting: https://docs.google.com/document/u/2/d/e/2PACX-1vTUCmj7aUdnMAdunG0AZo0AdWK-9jvfXcB7DWYmzGtmPc0IuIPGn7eLARoR5tBd6XUUB08W-hH74k-T/pub

Updated by greggzst (Grzegorz Jakubiak) 5 months ago

alfonsojimenez (Alfonso Jiménez) wrote:

I've updated the patch file increasing the ruby version in spec/ruby/core/enumerable/filter_map_spec.rb

Enumerable#filter_map was already accepted in the last developers meeting: https://docs.google.com/document/u/2/d/e/2PACX-1vTUCmj7aUdnMAdunG0AZo0AdWK-9jvfXcB7DWYmzGtmPc0IuIPGn7eLARoR5tBd6XUUB08W-hH74k-T/pub

Does the syntax allow for this kind of code?

(1..10).filter_map(&:even?) { |i| i * 2 }

Updated by matz (Yukihiro Matsumoto) 4 months ago

I accepted the proposal at the last developer meeting but forgot to post here.
I do reject having both block and block argument at the same time. [ruby-core:92505]
Regarding filter_map!, submit a new proposal, if you really needed (with the use-case).

Matz.

#16

Updated by alfonsojimenez (Alfonso Jiménez) 4 months ago

  • Status changed from Open to Closed

Applied in changeset git|0acbdd1ed0d2302743525a5188cc5a0d6251680c.


Adding Enumerable#filter_map

[Feature #15323]
Closes: https://github.com/ruby/ruby/pull/2017

Updated by nobu (Nobuyoshi Nakada) 4 months ago

IIRC, at the last meeting (20190522), the conclusion was that this method should select non-nil values only, like as Array#compact.
Am I correct?

Also available in: Atom PDF