Feature #17056
Updated by sawa (Tsuyoshi Sawada) over 4 years ago
The docs for `String#index` say: > If the second parameter is present, it specifies the position in the string to begin the search. So you can do: ```ruby > 'abcabc'.index('a',2) #=> 3 'abcabc'.index('a') #=> 0 ``` I would expect to also be able to do: ```ruby 'abcabc'.chars.index('a') #=> 0 'abcabc'.chars.index('a', 2) ArgumentError: wrong number of arguments (given 2, expected 0..1) from (pry):19:in `index' ``` After using this feature on strings, it is surprising to find that it is not available on arrays. ## Use case One use case I have for this is scanning a use case of finding file, trying to find the first matching line within a given section in a file. After finding section. So first I find the line number of the start of the section, and then I want to use that to find the first match after _after_ that line. My workaround for now is to use `with_index`: ```ruby lines = pathname.read.lines section_start_line = lines.index {|line| line.start_with?(/#* #{section_name}/) } lines.index(sought, section_start_line) ``` My workaround for now is to use `index.with_index`: ```ruby lines.index.with_index {|line, i| i > section_start_line && line.include?(sought) } ``` but I'd like to do it in a the more concise way using a feature of `Array#index` that I propose here, which is analogous to `String#index`. can do this with strings, given a starting position. ## Feature parity If the second parameter of `String#index` is present, it specifies the position in the string to begin the search: ```ruby 'abcabc'.index('a') # => 0 'abcabc'.index('a',2) # => 3 ``` I This would expect to also be able to do: ```ruby 'abcabc'.chars.index('a') # => 0 'abcabc'.chars.index('a', 2) ``` Using such feature, I would be able to do: ```ruby lines.index(sought, section_start_line) ``` This would give Ruby better parity with other programming languages that support this, like Python: ```python >>> list('abcabc') ['a', 'b', 'c', 'a', 'b', 'c'] >>> list('abcabc').index('a') 0 >>> list('abcabc').index('a', 2) 3 ``` ## End index too? We can further think of Ideally, we would also add an optional parameter to specify the position to end the search. The following languages allow specifying both start and end indexes: - [Python](https://docs.python.org/3/tutorial/datastructures.html) - [C#](https://docs.microsoft.com/en-us/dotnet/api/system.array.indexof?view=netcore-3.1) Ruby's index arg as well, but `String#index` does not have one, so we could make a separate proposal to add `end` to both methods at the same time. Other languages that allow specifying both start and end indexes: - [Python](https://docs.python.org/3/tutorial/datastructures.html) - [C#](https://docs.microsoft.com/en-us/dotnet/api/system.array.indexof?view=netcore-3.1) - ...