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

implemented intelligent slice functionality #414

Merged
merged 19 commits into from
Jun 12, 2021
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
90eb9aa
implemented slice function for stdlib_ascii
aman-godara May 23, 2021
e235bc4
added module dependencies of stdlib_math for function slice in Makefi…
aman-godara May 23, 2021
0742ca0
changed names from start to first and end to last
aman-godara May 24, 2021
1a5f78c
forgot to change the dummy argument start to first
aman-godara May 24, 2021
15827d2
shifted slice from stdlib_ascii to stdlib_strings and modified module…
aman-godara May 24, 2021
c7c1e48
removed include_last functionality
aman-godara May 25, 2021
ac607f1
added tests for slice function (with no include_last functionality)
aman-godara May 25, 2021
9d72c69
made complete use of slice interface: added test cases for character …
aman-godara May 25, 2021
a733bc3
documented function slice, corrected documentation of to_title and to…
aman-godara May 26, 2021
fa88905
improved function slice for invalid cases, added new invalid test cases
aman-godara May 27, 2021
42a905d
improved the implementation of last commit fa88905
aman-godara May 28, 2021
ffcb7e4
removed redundant outer loop, improved documentation of slice function
aman-godara May 29, 2021
4598eec
removed dependency of clip function by stdlib_strings.f90
aman-godara May 29, 2021
24d417f
improved documentation and comments for function slice
aman-godara Jun 7, 2021
323bcd9
Add general tester against intrinsic array slice
awvwgk Jun 10, 2021
a895085
Merge pull request #3 from awvwgk/slice
aman-godara Jun 10, 2021
d60dad3
added -inf and +inf concept to make code more intuitive, added descri…
aman-godara Jun 11, 2021
048b638
added the concept of +inf and -inf in documentation
aman-godara Jun 11, 2021
d38e0f4
added fail messages to unit tests
aman-godara Jun 11, 2021
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
4 changes: 2 additions & 2 deletions doc/specs/stdlib_string_type.md
Original file line number Diff line number Diff line change
Expand Up @@ -1254,7 +1254,7 @@ The result is a scalar `string_type` value.

```fortran
program demo_to_title
use stdlib_string_type, only: string_type, to_title
use stdlib_string_type
ivan-pi marked this conversation as resolved.
Show resolved Hide resolved
implicit none
type(string_type) :: string, titlecase_string

Expand Down Expand Up @@ -1302,7 +1302,7 @@ The result is a scalar `string_type` value.

```fortran
program demo_to_sentence
use stdlib_string_type, only: string_type, to_sentence
use stdlib_string_type
implicit none
type(string_type) :: string, sentencecase_string

Expand Down
71 changes: 71 additions & 0 deletions doc/specs/stdlib_strings.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,74 @@ program demo
print'(a)', ends_with("pattern", "pat") ! F
end program demo
```


<!-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -->
### `slice`

#### Description

Extracts the characters from the defined region of the input string.
Argument `first` and `last` defines the region for the function `slice` to operate.
aman-godara marked this conversation as resolved.
Show resolved Hide resolved
If the defined region is invalid (user provides atleast one invalid index), `first` and
`last` indexes are converted to first and last valid indexes in this defined region respectively,
if no valid index exists in this region an empty string is returned.

`stride` can attain both negative or positive values but when the invalid value
0 is given, it is converted to 1.
Extraction starts from `first` index and takes stride of length `stride`.
Extraction starts only if `last` index is crossable from `first` index by taking
stride of length `stride`and is active until `last` index is crossed.
Function automatically deduces the optional arguments that are not provided by the user.

#### Syntax

`string = [[stdlib_strings(module):slice(interface)]] (string, first, last, stride)`

#### Status

Experimental

#### Class

Pure function.

#### Argument

- `string`: Character scalar or [[stdlib_string_type(module):string_type(type)]]
This argument is intent(in).
- `first`: integer
This argument is intent(in) and optional.
- `last`: integer
This argument is intent(in) and optional.
- `stride`: integer
This argument is intent(in) and optional.

#### Result value

The result is of the same type as `string`.

#### Example

```fortran
program demo_slice
use stdlib_string_type
use stdlib_strings, only : slice
implicit none
type(string_type) :: string
character(len=10) :: char

string = "abcdefghij"
! string <-- "abcdefghij"

char = "abcdefghij"
! char <-- "abcdefghij"

print'(a)', slice("abcdefghij", 2, 6, 2) ! "bdf"
print'(a)', slice(char, 2, 6, 2) ! "bdf"

string = slice(string, 2, 6, 2)
! string <-- "bdf"

end program demo_slice
```
6 changes: 4 additions & 2 deletions src/Makefile.manual
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ stdlib_stats_var.o: \
stdlib_stats_distribution_PRNG.o: \
stdlib_kinds.o \
stdlib_error.o
stdlib_string_type.o: stdlib_ascii.o stdlib_kinds.o
stdlib_strings.o: stdlib_ascii.o stdlib_string_type.o
stdlib_string_type.o: stdlib_ascii.o \
stdlib_kinds.o
stdlib_strings.o: stdlib_ascii.o \
stdlib_string_type.o
stdlib_math.o: stdlib_kinds.o
76 changes: 76 additions & 0 deletions src/stdlib_strings.f90
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module stdlib_strings

public :: strip, chomp
public :: starts_with, ends_with
public :: slice


!> Remove leading and trailing whitespace characters.
Expand Down Expand Up @@ -57,6 +58,14 @@ module stdlib_strings
module procedure :: ends_with_char_string
module procedure :: ends_with_char_char
end interface ends_with

!> Extracts characters from the input string to return a new string
!>
!> Version: experimental
interface slice
module procedure :: slice_string
module procedure :: slice_char
end interface slice


contains
Expand Down Expand Up @@ -290,5 +299,72 @@ elemental function ends_with_string_string(string, substring) result(match)

end function ends_with_string_string

!> Extract the characters from the region between 'first' and 'last' index (both inclusive)
!> of the input 'string' by taking strides of length 'stride'
!> Returns a new string
elemental function slice_string(string, first, last, stride) result(sliced_string)
everythingfunctional marked this conversation as resolved.
Show resolved Hide resolved
type(string_type), intent(in) :: string
integer, intent(in), optional :: first, last, stride
type(string_type) :: sliced_string

sliced_string = string_type(slice(char(string), first, last, stride))

end function slice_string

!> Extract the characters from the region between 'first' and 'last' index (both inclusive)
!> of the input 'string' by taking strides of length 'stride'
!> Returns a new string
pure function slice_char(string, first, last, stride) result(sliced_string)
character(len=*), intent(in) :: string
integer, intent(in), optional :: first, last, stride
integer :: first_index, last_index, stride_vector, strides_taken, length_string, i, j
character(len=:), allocatable :: sliced_string
length_string = len(string)

first_index = 1
last_index = length_string
stride_vector = 1

if (present(stride)) then
if (stride /= 0) then
if (stride < 0) then
first_index = length_string
last_index = 1
end if
stride_vector = stride
end if
else
if (present(first) .and. present(last)) then
if (last < first) then
stride_vector = -1
end if
end if
end if

if (present(first)) then
first_index = first
end if
if (present(last)) then
last_index = last
end if

if (stride_vector > 0) then
first_index = max(first_index, 1)
last_index = min(last_index, length_string)
else
first_index = min(first_index, length_string)
last_index = max(last_index, 1)
end if

strides_taken = floor( real(last_index - first_index)/real(stride_vector) )
allocate(character(len=max(0, strides_taken + 1)) :: sliced_string)

j = 1
do i = first_index, last_index, stride_vector
sliced_string(j:j) = string(i:i)
j = j + 1
end do
end function slice_char


end module stdlib_strings
Loading