Project

General

Profile

Actions

Feature #18135

open

Introduce Enumerable#detect_only

Feature #18135: Introduce Enumerable#detect_only

Added by meisel (Michael Eisel) about 4 years ago. Updated about 4 years ago.

Status:
Open
Assignee:
-
Target version:
-
[ruby-core:105074]

Description

It can be important to get the only element for which a block returns true, and to assert that this is the only element as such. For example, this can be a very helpful sanity check when one is working with data that's outside of their control and is not perfectly understood. They may have a guess as to how to get a specific element matching some criteria, but if they used Enumerable#detect might be hiding the fact that they have written an incorrect block and that there's in fact more than one element that matches it. It could also be a parameter on Typically, I'd do it like this:

matches = array.select { |elem| some_method(elem) }
raise if matches.size != 0
match = matches.first

Here, it would be shortened to:

match = array.detect_only { |elem| some_method(elem) }

It could also be a parameter on Enumerable#detect instead of a separate method.


Related issues 1 (0 open1 closed)

Related to Ruby - Feature #13683: Add strict Enumerable#singleFeedbackActions

Updated by jeremyevans0 (Jeremy Evans) about 4 years ago Actions #1

  • Tracker changed from Bug to Feature
  • Backport deleted (2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN)

Updated by meisel (Michael Eisel) about 4 years ago Actions #2 [ruby-core:105106]

Also, another alternative could be Enumerable#take_only, where it takes the only element from the enumerable or else fails. So instead of:

array.detect_only { |elem| some_method(elem) }

We'd have:

array.select { |elem| some_method(elem) }.take_only

Updated by duerst (Martin Dürst) about 4 years ago Actions #3 [ruby-core:105110]

meisel (Michael Eisel) wrote in #note-2:

Also, another alternative could be Enumerable#take_only, where it takes the only element from the enumerable or else fails. So instead of:

array.detect_only { |elem| some_method(elem) }

We'd have:

array.select { |elem| some_method(elem) }.take_only

It's a good idea to separate things out, but this could be highly inefficient (checking and selecting lots of elements only to find out later that there's more than one).

Updated by mame (Yusuke Endoh) about 4 years ago Actions #4

Updated by mame (Yusuke Endoh) about 4 years ago Actions #5 [ruby-core:105112]

Do you mean raise if matches.size != 1 instead of ... != 0?

The idea of take_only is already proposed in #13683.

Updated by meisel (Michael Eisel) about 4 years ago Actions #6 [ruby-core:105123]

Yes, I meant ... != 1, thanks. And I think we can close this issue, and I'll add my thoughts to the issue that this dupes.

Actions

Also available in: PDF Atom