Return a list of substring in the string, using sep as the delimiter string, chunked (memory-efficient) algorithm.
@note Note Multiple subsequent separators are collapsed to one occurrence.
@note Note
The split is performed in chunks of #chunks
to avoid excessive memory consumption.
type(string) :: astring
type(string), allocatable :: strings(:)
logical :: test_passed(1)
astring = '-1-2-3-4-5-6-7-8-'
call astring%split_chunked(tokens=strings, sep='-', chunks=3)
test_passed(1) = (strings(1)//''=='1'.and.strings(2)//''=='2'.and.strings(3)//''=='3'.and.strings(4)//''=='4'.and. &
strings(5)//''=='5'.and.strings(6)//''=='6'.and.strings(7)//''=='7'.and.strings(8)//''=='8')
print '(L1)', all(test_passed)
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(string), | intent(in) | :: | self |
The string. |
||
type(string), | intent(out), | allocatable | :: | tokens(:) |
Tokens substring. |
|
integer, | intent(in) | :: | chunks |
Number of chunks. |
||
character(kind=CK, len=*), | intent(in), | optional | :: | sep |
Separator. |
pure subroutine split_chunked(self, tokens, chunks, sep) !< Return a list of substring in the string, using sep as the delimiter string, chunked (memory-efficient) algorithm. !< !< @note Multiple subsequent separators are collapsed to one occurrence. !< !< @note The split is performed in chunks of `#chunks` to avoid excessive memory consumption. !< !<```fortran !< type(string) :: astring !< type(string), allocatable :: strings(:) !< logical :: test_passed(1) !< astring = '-1-2-3-4-5-6-7-8-' !< call astring%split_chunked(tokens=strings, sep='-', chunks=3) !< test_passed(1) = (strings(1)//''=='1'.and.strings(2)//''=='2'.and.strings(3)//''=='3'.and.strings(4)//''=='4'.and. & !< strings(5)//''=='5'.and.strings(6)//''=='6'.and.strings(7)//''=='7'.and.strings(8)//''=='8') !< print '(L1)', all(test_passed) !<``` !=> T <<< class(string), intent(in) :: self !< The string. type(string), allocatable, intent(out) :: tokens(:) !< Tokens substring. integer, intent(in) :: chunks !< Number of chunks. character(kind=CK, len=*), intent(in), optional :: sep !< Separator. character(kind=CK, len=:), allocatable :: sep_ !< Separator, default value. integer :: Nt !< Number of actual tokens. integer :: t !< Counter. logical :: isok if (allocated(self%raw)) then sep_ = SPACE ; if (present(sep)) sep_ = sep Nt = self%count(sep_) if (self%start_with(prefix=sep_)) Nt = Nt - 1 if (self%end_with(suffix=sep_)) Nt = Nt - 1 t = 0 call self%split(tokens=tokens, sep=sep_, max_tokens=chunks) do t = size(tokens, dim=1) if (t > Nt) exit call split_last_token(tokens=tokens, max_tokens=chunks,isok=isok) if(isok)then else exit endif enddo t = size(tokens, dim=1) if (tokens(t)%count(sep_) > 0) then call split_last_token(tokens=tokens,isok=isok) endif endif contains pure subroutine split_last_token(tokens, max_tokens,isok) !< Split last token. type(string), allocatable, intent(inout) :: tokens(:) !< Tokens substring. integer, intent(in), optional :: max_tokens !< Max tokens returned. type(string), allocatable :: tokens_(:) !< Temporary tokens. type(string), allocatable :: tokens_swap(:) !< Swap tokens. integer :: Nt_ !< Number of last created tokens. logical,intent(out) :: isok isok=.true. call tokens(t)%split(tokens=tokens_, sep=sep_, max_tokens=max_tokens) if (allocated(tokens_)) then Nt_ = size(tokens_, dim=1) if (Nt_ >= 1) then allocate(tokens_swap(1:t-1+Nt_)) tokens_swap(1:t-1) = tokens(1:t-1) tokens_swap(t:) = tokens_(:) call move_alloc(from=tokens_swap, to=tokens) endif if (Nt_ == 1) then isok=.false. end if deallocate(tokens_) endif endsubroutine split_last_token endsubroutine split_chunked