Appearance
3. Splitting and joining
A row of the table is one line of text: the values are between the commas.
Split
f90
row = '1999, Chevy, Venture, 4900.50, extended edition'
call row%split(tokens=cells, sep=',')
print '(I0,A)', size(cells), ' cells'
cells = cells%strip() ! elemental: every cell at once
do c = 1, size(cells)
print '(I0,A)', c, ': ['//cells(c)//']'
enddosplit is a subroutine: it allocates tokens with one string for each piece, of the length of that piece. The cells still carry the blank after each comma, and here is one of the strengths of the type: the methods are elemental, so cells%strip() strips every element of the array in one statement.
Join
f90
print '(A)', '| '//glue%join(array=cells, sep=' | ')//' |'
glue = '-'
print '(A)', glue%join(array=cells(2:3))//'' ! the string itself is the separatorjoin is the opposite of split: it concatenates the elements of an array, with a separator between them. The separator is sep, or the string on which join is called when sep is not passed.
Partition
f90
pieces = row%partition(sep=', ') ! before, separator, after
print '(A)', 'year: '//pieces(1)
print '(A)', 'rest: '//pieces(3)
print '(A,I0)', 'commas: ', row%count(',')partition splits once, at the first separator, and returns three strings: what is before, the separator, what is after. count counts the occurrences of a substring.
Find
f90
print '(2(L1,1X))', row%start_with('1999'), row%end_with('edition')
print '(A,I0)', 'second comma at ', row%index(',', occurrence=2)
print '(A,I0)', 'last comma at ', row%index(',', back=.true.)start_with and end_with test the ends of the string; index is the position of a substring, as the intrinsic, the last one with back=.true., the k-th one with occurrence=k: here the comma before the model. count and index look for occurrences that do not overlap, as Python does; count(substring, overlapping=.true.) counts the overlapping ones too.
Empty fields
f90
record = '2003,Fiat,,1800,' ! the model and the notes are missing
call record%split(tokens=cells, sep=',')
print '(I0,A)', size(cells), ' tokens: '//glue%join(array=cells, sep='|')
call record%split(tokens=cells, sep=',', keep_empty=.true.)
print '(I0,A)', size(cells), ' fields: '//glue%join(array=cells, sep='|')split counts repeated separators as one and ignores the ones at the ends: a record with missing values loses their position. With keep_empty=.true. every separator splits and the empty fields are tokens, as in Python str.split(','): the fields of a CSV record stay in their columns.
Running it
$ report
5 cells
1: [1999]
2: [Chevy]
3: [Venture]
4: [4900.50]
5: [extended edition]
| 1999 | Chevy | Venture | 4900.50 | extended edition |
Chevy-Venture
year: 1999
rest: Chevy, Venture, 4900.50, extended edition
commas: 4
T T
second comma at 12
last comma at 30
3 tokens: 2003|Fiat|1800
5 fields: 2003|Fiat||1800|The whole program:
f90
program report
!< Tutorial, chapter 3: splitting and joining.
use stringifor
implicit none
type(string) :: row, glue, pieces(3), record
type(string), allocatable :: cells(:)
integer :: c
row = '1999, Chevy, Venture, 4900.50, extended edition'
call row%split(tokens=cells, sep=',')
print '(I0,A)', size(cells), ' cells'
cells = cells%strip() ! elemental: every cell at once
do c = 1, size(cells)
print '(I0,A)', c, ': ['//cells(c)//']'
enddo
print '(A)', '| '//glue%join(array=cells, sep=' | ')//' |'
glue = '-'
print '(A)', glue%join(array=cells(2:3))//'' ! the string itself is the separator
pieces = row%partition(sep=', ') ! before, separator, after
print '(A)', 'year: '//pieces(1)
print '(A)', 'rest: '//pieces(3)
print '(A,I0)', 'commas: ', row%count(',')
print '(2(L1,1X))', row%start_with('1999'), row%end_with('edition')
print '(A,I0)', 'second comma at ', row%index(',', occurrence=2)
print '(A,I0)', 'last comma at ', row%index(',', back=.true.)
record = '2003,Fiat,,1800,' ! the model and the notes are missing
call record%split(tokens=cells, sep=',')
print '(I0,A)', size(cells), ' tokens: '//glue%join(array=cells, sep='|')
call record%split(tokens=cells, sep=',', keep_empty=.true.)
print '(I0,A)', size(cells), ' fields: '//glue%join(array=cells, sep='|')
endprogram reportWhat you learned
split into an allocatable array, with or without the empty fields; join back, partition for one split; start_with, end_with, index and count to find things; methods applied to a whole array. Reference: String Manipulation.
Next: 4. Numbers.