Project

General

Profile

Actions

Feature #22536

open

Add Enumerable#longest_slice to return the range of the longest consecutive matching sequence

Feature #22536: Add Enumerable#longest_slice to return the range of the longest consecutive matching sequence

Added by datibbaw (Tjerk Meesters) 2 days ago. Updated about 22 hours ago.

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

Description

I propose adding Enumerable#longest_slice, which returns a Range identifying the longest consecutive sequence of matching entries.

Without a block, entries match when they are truthy. Both nil and false break a sequence. With a block, entries match when the block returns a truthy value.

Motivation

Finding the longest consecutive matching sequence currently requires manually tracking positions and run lengths, or creating intermediate collections. Returning a Range makes the result directly usable for slicing an Array or identifying positions in another enumerable.

I ran into this when analysing IPv6 compression logic and reasoned that it may have other uses; in comparison, longest prefix / suffix is already covered with e.g. #index and #rindex using block syntax.

Examples

[nil, 'a', 'b', nil, 'c'].longest_slice
# => 1...3

[1, 2, 4, 3, 6].longest_slice(&:even?)
# => 1...3

[false, 0, []].longest_slice
# => 1...3

a = [10, 20, 30, 40]
a.each.with_index(1).longest_slice do |value, index|
  value >= 20 && index <= 3
end
# => 1...3

Proposed behavior

  • Return a zero-based, end-exclusive Range.
  • Return 0...0 for an empty enumerable or when no entries match.
  • When multiple matching sequences have the same maximum length, return the first.
  • Forward all arguments yielded by each to the block, supporting indexed enumerators and multi-argument iterators.
  • Always express the result in iteration positions, independently of any index yielded to the block.
  • Traverse the enumerable once, using constant auxiliary space.

The name longest_slice and the API details are open for discussion.

A draft implementation with documentation and tests is available at:
https://github.com/ruby/ruby/pull/19838

Actions

Also available in: PDF Atom