@@ -1251,18 +1251,14 @@ def join_on_conjunctions(self, pieces: list[str], additional_parts_count: int =
12511251
12521252 contiguous_conj_i = group_contiguous_integers (conj_index )
12531253
1254- delete_i : list [int ] = []
1255- for cont_i in contiguous_conj_i :
1254+ # process ranges in reverse so deleting one range doesn't shift the
1255+ # indices of ranges still to be processed
1256+ for cont_i in reversed (contiguous_conj_i ):
12561257 new_piece = " " .join (pieces [cont_i [0 ]: cont_i [1 ]+ 1 ])
1257- delete_i += list (range (cont_i [0 ]+ 1 , cont_i [1 ]+ 1 ))
1258- pieces [cont_i [0 ]] = new_piece
1258+ pieces [cont_i [0 ]:cont_i [1 ]+ 1 ] = [new_piece ]
12591259 # add newly joined conjunctions to constants to be found later
12601260 self .C .conjunctions .add (new_piece )
12611261
1262- for i in reversed (delete_i ):
1263- # delete pieces in reverse order or the index changes on each delete
1264- del pieces [i ]
1265-
12661262 if len (pieces ) == 1 :
12671263 # if there's only one piece left, nothing left to do
12681264 return pieces
@@ -1295,70 +1291,36 @@ def shift_conj_index(past: int, by: int) -> None:
12951291 # http://code.google.com/p/python-nameparser/issues/detail?id=11
12961292 continue
12971293
1298- if i == 0 :
1299- new_piece = " " .join (pieces [i :i + 2 ])
1300- register_joined_piece (new_piece , pieces [i + 1 ])
1301- pieces [i ] = new_piece
1302- pieces .pop (i + 1 )
1303- shift_conj_index (past = i , by = 1 )
1304-
1305- else :
1306- new_piece = " " .join (pieces [i - 1 :i + 2 ])
1307- register_joined_piece (new_piece , pieces [i - 1 ])
1308- pieces [i - 1 ] = new_piece
1309- # len(pieces) - i is always >= 1 here: pieces[i-1:i+2] above
1310- # already accessed index i, so i is guaranteed in range.
1311- rm_count = min (2 , len (pieces ) - i )
1312- assert rm_count > 0 , f"unexpected empty deletion at i={ i } , pieces={ pieces } "
1313- del pieces [i :i + rm_count ]
1314- shift_conj_index (past = i , by = rm_count )
1294+ start = max (0 , i - 1 )
1295+ end = min (len (pieces ), i + 2 )
1296+ new_piece = " " .join (pieces [start :end ])
1297+ neighbor = pieces [start ] if start < i else pieces [end - 1 ]
1298+ register_joined_piece (new_piece , neighbor )
1299+ pieces [start :end ] = [new_piece ]
1300+ shift_conj_index (past = i , by = end - start - 1 )
13151301
13161302 # join prefixes to following lastnames: ['de la Vega'], ['van Buren']
1317- prefixes = list (filter (self .is_prefix , pieces ))
1318- if prefixes :
1319- for prefix in prefixes :
1320- try :
1321- i = pieces .index (prefix )
1322- except ValueError :
1323- # If the prefix is no longer in pieces, it's because it has been
1324- # combined with the prefix that appears right before (or before that when
1325- # chained together) in the last loop, so the index of that newly created
1326- # piece is the same as in the last loop, i==i still, and we want to join
1327- # it to the next piece.
1328- pass
1303+ i = 0
1304+ while i < len (pieces ):
1305+ # total_length >= 1 covers essentially all real input, so this
1306+ # treats any leading piece as a first name rather than a prefix.
1307+ leading_first_name = i == 0 and total_length >= 1
1308+ if not self .is_prefix (pieces [i ]) or leading_first_name :
1309+ i += 1
1310+ continue
13291311
1330- new_piece = ''
1312+ # absorb any immediately-adjacent prefixes into one contiguous run
1313+ # e.g. "von und zu der" ==> chain them all before looking further
1314+ j = i + 1
1315+ while j < len (pieces ) and self .is_prefix (pieces [j ]):
1316+ j += 1
13311317
1332- # join everything after the prefix until the next prefix or suffix
1318+ # then join everything after the run until the next prefix or suffix
1319+ while j < len (pieces ) and not self .is_prefix (pieces [j ]) and not self .is_suffix (pieces [j ]):
1320+ j += 1
13331321
1334- try :
1335- if i == 0 and total_length >= 1 :
1336- # If it's the first piece and there are more than 1 rootnames, assume it's a first name
1337- continue
1338- next_prefix = next (iter (filter (self .is_prefix , pieces [i + 1 :])))
1339- j = pieces .index (next_prefix , i + 1 )
1340- if j == i + 1 :
1341- # if there are two prefixes in sequence, join to the following piece
1342- j += 1
1343- new_piece = ' ' .join (pieces [i :j ])
1344- pieces [i :j ] = [new_piece ]
1345- except StopIteration :
1346- try :
1347- # if there are no more prefixes, look for a suffix to stop at
1348- stop_at = next (iter (filter (self .is_suffix , pieces [i + 1 :])))
1349- # search from i + 1: filter() finds the value of stop_at
1350- # in pieces[i+1:] but pieces.index() without a start
1351- # argument searches from 0, so an earlier occurrence of
1352- # the same token (e.g. a suffix token that also appears
1353- # before the prefix) would be matched instead.
1354- j = pieces .index (stop_at , i + 1 )
1355- new_piece = ' ' .join (pieces [i :j ])
1356- pieces [i :j ] = [new_piece ]
1357- except StopIteration :
1358- # if there were no suffixes, nothing to stop at so join all
1359- # remaining pieces
1360- new_piece = ' ' .join (pieces [i :])
1361- pieces [i :] = [new_piece ]
1322+ pieces [i :j ] = [' ' .join (pieces [i :j ])]
1323+ i += 1
13621324
13631325 log .debug ("pieces: %s" , pieces )
13641326 return pieces
0 commit comments