From 3ddbd0ad1d3d512c16a3c5364aadc8b4334a83d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Mon, 2 Oct 2017 09:57:04 +0200 Subject: [PATCH 1/5] first and last with nchar --- NEWS.md | 6 ++++- base/strings/basic.jl | 47 +++++++++++++++++++++++++++++++++++++++ doc/src/stdlib/strings.md | 2 ++ test/strings/basic.jl | 20 +++++++++++++++++ 4 files changed, 74 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 4419d4d7f67e9..0f9df2e7f22ae 100644 --- a/NEWS.md +++ b/NEWS.md @@ -236,8 +236,12 @@ This section lists changes that do not have deprecation warnings. Library improvements -------------------- + * Functions `first` and `last` now accept `nchar` argument for `AbstractString`. + If this argument is used they reutrn a substring consisting of first/last `nchar` + characters from the original string ([#?????]). + * The functions `nextind` and `prevind` now accept `nchar` argument that indicates - number of characters to move ([#23805]). + the number of characters to move ([#23805]). * The functions `strip`, `lstrip` and `rstrip` now return `SubString` ([#22496]). diff --git a/base/strings/basic.jl b/base/strings/basic.jl index c6c572882ce66..718a34b5b89a1 100644 --- a/base/strings/basic.jl +++ b/base/strings/basic.jl @@ -610,3 +610,50 @@ function filter(f, s::AbstractString) end String(take!(out)) end + +## string first and last ## + +""" + first(str::AbstractString, nchar::Integer) + +Get a string consisting of first `nchar` characters of `str`. + +```jldoctest +julia> first("∀ϵ≠0: ϵ²>0", 0) +"" + +julia> first("∀ϵ≠0: ϵ²>0", 1) +"∀" + +julia> first("∀ϵ≠0: ϵ²>0", 3) +"∀ϵ≠" +``` +""" +function first(str::AbstractString, nchar::Integer) + nchar == 0 && return "" + nchar == 1 && return str[1:1] + str[1:nextind(str, 1, nchar-1)] +end + +""" + last(str::AbstractString, nchar::Integer) + +Get a string consisting of last `nchar` characters of `str`. + +```jldoctest +julia> last("∀ϵ≠0: ϵ²>0", 0) +"" + +julia> last("∀ϵ≠0: ϵ²>0", 1) +"0" + +julia> last("∀ϵ≠0: ϵ²>0", 3) +"²>0" +``` +""" +function last(str::AbstractString, nchar::Integer) + nchar == 0 && return "" + e = endof(str) + nchar == 1 && return str[e:e] + str[prevind(str, e, nchar-1):e] +end diff --git a/doc/src/stdlib/strings.md b/doc/src/stdlib/strings.md index 003b9b1b92b6d..2d00e04bbe39b 100644 --- a/doc/src/stdlib/strings.md +++ b/doc/src/stdlib/strings.md @@ -46,6 +46,8 @@ Base.lstrip Base.rstrip Base.startswith Base.endswith +Base.first(::AbstractString, ::Integer) +Base.last(::AbstractString, ::Integer) Base.uppercase Base.lowercase Base.titlecase diff --git a/test/strings/basic.jl b/test/strings/basic.jl index 2da583f9474b5..33719b3507384 100644 --- a/test/strings/basic.jl +++ b/test/strings/basic.jl @@ -623,3 +623,23 @@ end @test prevind(strs[2], -1, 1) == 0 end end + +@testset "first and last" begin + s = "∀ϵ≠0: ϵ²>0" + @test_throws ArgumentError first(s, -1) + @test first(s, 0) == "" + @test first(s, 1) == "∀" + @test first(s, 2) == "∀ϵ" + @test first(s, 3) == "∀ϵ≠" + @test first(s, 4) == "∀ϵ≠0" + @test first(s, length(s)) == s + @test_throws BoundsError first(s, length(s)+1) + @test_throws ArgumentError last(s, -1) + @test last(s, 0) == "" + @test last(s, 1) == "0" + @test last(s, 2) == ">0" + @test last(s, 3) == "²>0" + @test last(s, 4) == "ϵ²>0" + @test last(s, length(s)) == s + @test_throws BoundsError last(s, length(s)+1) +end From df78dbe70e636c7426a4ae27a35c79d2e958f2a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Mon, 2 Oct 2017 10:40:30 +0200 Subject: [PATCH 2/5] improve description --- NEWS.md | 2 +- base/strings/basic.jl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/NEWS.md b/NEWS.md index 0f9df2e7f22ae..f8bc36b15355e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -237,7 +237,7 @@ Library improvements -------------------- * Functions `first` and `last` now accept `nchar` argument for `AbstractString`. - If this argument is used they reutrn a substring consisting of first/last `nchar` + If this argument is used they reutrn a string consisting of first/last `nchar` characters from the original string ([#?????]). * The functions `nextind` and `prevind` now accept `nchar` argument that indicates diff --git a/base/strings/basic.jl b/base/strings/basic.jl index 718a34b5b89a1..dc6a8257479ba 100644 --- a/base/strings/basic.jl +++ b/base/strings/basic.jl @@ -616,7 +616,7 @@ end """ first(str::AbstractString, nchar::Integer) -Get a string consisting of first `nchar` characters of `str`. +Get a string consisting of the first `nchar` characters of `str`. ```jldoctest julia> first("∀ϵ≠0: ϵ²>0", 0) @@ -638,7 +638,7 @@ end """ last(str::AbstractString, nchar::Integer) -Get a string consisting of last `nchar` characters of `str`. +Get a string consisting of the last `nchar` characters of `str`. ```jldoctest julia> last("∀ϵ≠0: ϵ²>0", 0) From b6d7e9f7c5a787636337842c18099b36250a6721 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Mon, 2 Oct 2017 10:42:09 +0200 Subject: [PATCH 3/5] add PR number --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index f8bc36b15355e..bf492b68b2d78 100644 --- a/NEWS.md +++ b/NEWS.md @@ -238,7 +238,7 @@ Library improvements * Functions `first` and `last` now accept `nchar` argument for `AbstractString`. If this argument is used they reutrn a string consisting of first/last `nchar` - characters from the original string ([#?????]). + characters from the original string ([#23960]). * The functions `nextind` and `prevind` now accept `nchar` argument that indicates the number of characters to move ([#23805]). From 68098d2a234807b1954fe887a7e74a540db3fa9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Mon, 2 Oct 2017 10:51:53 +0200 Subject: [PATCH 4/5] fix typo --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index bf492b68b2d78..744c302b85d5f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -237,7 +237,7 @@ Library improvements -------------------- * Functions `first` and `last` now accept `nchar` argument for `AbstractString`. - If this argument is used they reutrn a string consisting of first/last `nchar` + If this argument is used they return a string consisting of first/last `nchar` characters from the original string ([#23960]). * The functions `nextind` and `prevind` now accept `nchar` argument that indicates From 9fbb56803451a4e9e8798a40b1951a81ce98b99e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Mon, 2 Oct 2017 11:26:30 +0200 Subject: [PATCH 5/5] make first/last type stable --- base/strings/basic.jl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/base/strings/basic.jl b/base/strings/basic.jl index dc6a8257479ba..52c1a32c1eee9 100644 --- a/base/strings/basic.jl +++ b/base/strings/basic.jl @@ -630,8 +630,9 @@ julia> first("∀ϵ≠0: ϵ²>0", 3) ``` """ function first(str::AbstractString, nchar::Integer) - nchar == 0 && return "" - nchar == 1 && return str[1:1] + if 0 <= nchar <= 1 + return str[1:nchar] + end str[1:nextind(str, 1, nchar-1)] end @@ -652,8 +653,9 @@ julia> last("∀ϵ≠0: ϵ²>0", 3) ``` """ function last(str::AbstractString, nchar::Integer) - nchar == 0 && return "" e = endof(str) - nchar == 1 && return str[e:e] + if 0 <= nchar <= 1 + return str[(e-nchar+1):e] + end str[prevind(str, e, nchar-1):e] end