Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add head and tail arguments to chop #24126

Merged
merged 5 commits into from
Oct 19, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,9 @@ This section lists changes that do not have deprecation warnings.
Library improvements
--------------------

* The function `chop` now accepts two arguments `head` and `tail` allowing to specify
number of characters to remove from the head and tail of the string ([#24126]).

* Functions `first` and `last` now accept `nchar` argument for `AbstractString`.
If this argument is used they return a string consisting of first/last `nchar`
characters from the original string ([#23960]).
Expand Down
23 changes: 20 additions & 3 deletions base/strings/util.jl
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,12 @@ startswith(a::Vector{UInt8}, b::Vector{UInt8}) =
# TODO: fast endswith

"""
chop(s::AbstractString)
chop(s::AbstractString, head::Integer=0, tail::Integer=1)

Remove the last character from `s`.
Remove the first `head` and the last `tail` characters from `s`.
The call `chop(s)` removes the last character from `s`.
If it is requested to remove more characters than `length(s)`
then an empty string is returned.

# Examples
```jldoctest
Expand All @@ -77,9 +80,23 @@ julia> a = "March"

julia> chop(a)
"Marc"

julia> chop(a, 1, 2)
"ar"

julia> chop(a, 5, 5)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The description should mention that no error is thrown if there are not enough characters.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added. This is the current behavior as chop("") returns "".

""
```
"""
chop(s::AbstractString) = SubString(s, 1, prevind(s, endof(s)))
function chop(s::AbstractString, head::Integer, tail::Integer)
# negative values of head/tail will throw error in nextind/prevind
headidx = head == 0 ? start(s) : nextind(s, start(s), head)
tailidx = tail == 0 ? endof(s) : prevind(s, endof(s), tail)
SubString(s, headidx, tailidx)
end

# no head/tail version left for performance reasons
chop(s::AbstractString) = SubString(s, start(s), prevind(s, endof(s)))

"""
chomp(s::AbstractString)
Expand Down
20 changes: 20 additions & 0 deletions test/strings/util.jl
Original file line number Diff line number Diff line change
Expand Up @@ -231,10 +231,30 @@ end
@testset "chomp/chop" begin
@test chomp("foo\n") == "foo"
@test chomp("fo∀\n") == "fo∀"
@test chomp("foo\r\n") == "foo"
@test chomp("fo∀\r\n") == "fo∀"
@test chomp("fo∀") == "fo∀"
@test chop("fooε") == "foo"
@test chop("foεo") == "foε"
@test chop("∃∃∃∃") == "∃∃∃"
@test chop("∀ϵ∃Δ", 0, 0) == "∀ϵ∃Δ"
@test chop("∀ϵ∃Δ", 0, 1) == "∀ϵ∃"
@test chop("∀ϵ∃Δ", 0, 2) == "∀ϵ"
@test chop("∀ϵ∃Δ", 0, 3) == "∀"
@test chop("∀ϵ∃Δ", 0, 4) == ""
@test chop("∀ϵ∃Δ", 0, 5) == ""
@test chop("∀ϵ∃Δ", 1, 0) == "ϵ∃Δ"
@test chop("∀ϵ∃Δ", 2, 0) == "∃Δ"
@test chop("∀ϵ∃Δ", 3, 0) == "Δ"
@test chop("∀ϵ∃Δ", 4, 0) == ""
@test chop("∀ϵ∃Δ", 5, 0) == ""
@test chop("∀ϵ∃Δ", 1, 1) == "ϵ∃"
@test chop("∀ϵ∃Δ", 2, 2) == ""
@test chop("∀ϵ∃Δ", 3, 3) == ""
@test_throws ArgumentError chop("∀ϵ∃Δ", -3, 3)
@test_throws ArgumentError chop("∀ϵ∃Δ", 3, -3)
@test_throws ArgumentError chop("∀ϵ∃Δ", -3, -3)

@test isa(chomp("foo"), SubString)
@test isa(chop("foo"), SubString)
end
Expand Down