From a9ce021d849fa68b3cbbcb3ec46ada5222d66ad0 Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Tue, 6 Sep 2022 02:52:29 +0800 Subject: [PATCH] Add `Indexable#index!` overloads with `offset` parameter (#12089) --- spec/std/indexable_spec.cr | 22 ++++++++++++++++++++++ src/indexable.cr | 26 ++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/spec/std/indexable_spec.cr b/spec/std/indexable_spec.cr index bd6ec348bf65..e2071cef0885 100644 --- a/spec/std/indexable_spec.cr +++ b/spec/std/indexable_spec.cr @@ -93,6 +93,28 @@ describe Indexable do end end + describe "#index!" do + it "offset type" do + indexable = SafeIndexable.new(3) + indexable.index!(1, 0_i64).should eq 1 + indexable.index!(1, 0_i64).should be_a(Int64) + end + + it "raises if no element is found" do + indexable = SafeIndexable.new(3) + expect_raises(Enumerable::NotFoundError) { indexable.index!(0, -100) } + expect_raises(Enumerable::NotFoundError) { indexable.index!(0, -4) } + expect_raises(Enumerable::NotFoundError) { indexable.index!(0, 1) } + expect_raises(Enumerable::NotFoundError) { indexable.index!(0, 3) } + expect_raises(Enumerable::NotFoundError) { indexable.index!(0, 100) } + + expect_raises(Enumerable::NotFoundError) { indexable.index!(-4) { true } } + expect_raises(Enumerable::NotFoundError) { indexable.index!(3) { true } } + expect_raises(Enumerable::NotFoundError) { indexable.index!(2) { false } } + expect_raises(Enumerable::NotFoundError) { indexable.index!(-3) { false } } + end + end + describe "#rindex" do it "does rindex with big negative offset" do indexable = SafeIndexable.new(3) diff --git a/src/indexable.cr b/src/indexable.cr index b052dbacd4fe..c05b6baf8c88 100644 --- a/src/indexable.cr +++ b/src/indexable.cr @@ -742,8 +742,8 @@ module Indexable(T) hasher end - # Returns the index of the first appearance of *value* in `self` - # starting from the given *offset*, or `nil` if the value is not in `self`. + # Returns the index of the first appearance of *object* in `self` + # starting from the given *offset*, or `nil` if *object* is not in `self`. # # ``` # [1, 2, 3, 1, 2, 3].index(2, offset: 2) # => 4 @@ -771,6 +771,28 @@ module Indexable(T) nil end + # Returns the index of the first appearance of *obj* in `self` + # starting from the given *offset*. Raises `Enumerable::NotFoundError` if + # *obj* is not in `self`. + # + # ``` + # [1, 2, 3, 1, 2, 3].index!(2, offset: 2) # => 4 + # ``` + def index!(obj, offset : Int = 0) + index(obj, offset) || raise Enumerable::NotFoundError.new + end + + # Returns the index of the first object in `self` for which the block + # is truthy, starting from the given *offset*. Raises + # `Enumerable::NotFoundError` if no match is found. + # + # ``` + # [1, 2, 3, 1, 2, 3].index!(offset: 2) { |x| x < 2 } # => 3 + # ``` + def index!(offset : Int = 0, & : T ->) + index(offset) { |e| yield e } || raise Enumerable::NotFoundError.new + end + # Returns the last element of `self` if it's not empty, or raises `IndexError`. # # ```