Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

247
Visualizações
Python split string by multiple delimiters following a hierarchy

I want to split strings only once based on multiple delimiters like "and", "&" and "-" in that order. Example:

'121 34 adsfd' -> ['121 34 adsfd']
'dsfsd and adfd' -> ['dsfsd ', ' adfd']
'dsfsd & adfd' -> ['dsfsd ', ' adfd']
'dsfsd - adfd' -> ['dsfsd ', ' adfd']
'dsfsd and adfd and adsfa' -> ['dsfsd ', ' adfd and adsfa']
'dsfsd and adfd - adsfa' -> ['dsfsd ', ' adfd - adsfa']
'dsfsd - adfd and adsfa' -> ['dsfsd - adfd ', ' adsfa']

I tried the below code to achieve this:

import re
re.split('and|&|-', string, maxsplit=1)

It works for all cases except the last one. As it does not follow the hierarchy, for the last one it returns:

'dsfsd - adfd and adsfa' -> ['dsfsd ', ' adfd and adsfa']

How can I achieve this?

over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

This would be impractical with a single regular expression. You could get it to work with negative lookbehinds, but it would get quite complicated with each additional delimiter. It's pretty trivial to do this with plain old str.split() and multiple lines. All you have to do is check if splitting with the current delimiter gives you two elements. If it does, that's your answer. If not, move on to the next delimiter:

def split_new(inp, delims):
    for d in delims:
        result = inp.split(d, maxsplit=1)
        if len(result) == 2: return result

    return [inp] # If nothing worked, return the input

To test this:

teststrs = ['121 34 adsfd' , 'dsfsd and adfd', 'dsfsd & adfd' , 'dsfsd - adfd' , 'dsfsd and adfd and adsfa' , 'dsfsd and adfd - adsfa' , 'dsfsd - adfd and adsfa' ]
for t in teststrs:
    print(repr(t), '->', split_new(t, ['and', '&', '-']))

outputs

'121 34 adsfd' -> ['121 34 adsfd']
'dsfsd and adfd' -> ['dsfsd ', ' adfd']
'dsfsd & adfd' -> ['dsfsd ', ' adfd']
'dsfsd - adfd' -> ['dsfsd ', ' adfd']
'dsfsd and adfd and adsfa' -> ['dsfsd ', ' adfd and adsfa']
'dsfsd and adfd - adsfa' -> ['dsfsd ', ' adfd - adsfa']
'dsfsd - adfd and adsfa' -> ['dsfsd - adfd ', ' adsfa']
over 4 years ago · Santiago Trujillo Relatório

0

Try:

import re

tests = [
    ["121 34 adsfd", ["121 34 adsfd"]],
    ["dsfsd and adfd", ["dsfsd ", " adfd"]],
    ["dsfsd & adfd", ["dsfsd ", " adfd"]],
    ["dsfsd - adfd", ["dsfsd ", " adfd"]],
    ["dsfsd and adfd and adsfa", ["dsfsd ", " adfd and adsfa"]],
    ["dsfsd and adfd - adsfa", ["dsfsd ", " adfd - adsfa"]],
    ["dsfsd - adfd and adsfa", ["dsfsd - adfd ", " adsfa"]],
]

for s, result in tests:
    res = re.split(r"and|&(?!.*and)|-(?!.*and|.*&)", s, maxsplit=1)
    print(res)
    assert res == result

Prints:

['121 34 adsfd']
['dsfsd ', ' adfd']
['dsfsd ', ' adfd']
['dsfsd ', ' adfd']
['dsfsd ', ' adfd and adsfa']
['dsfsd ', ' adfd - adsfa']
['dsfsd - adfd ', ' adsfa']

Explanation:

The regex and|&(?!.*and)|-(?!.*and|.*&) uses 3 alternatives.

  1. We match and always or:
  2. We match & only if there isn't and ahead (using the negative look-ahead (?! ) or:
  3. We match - only if there isn't and or & ahead.

We're using this pattern in re.sub -> splitting only on the first match.

over 4 years ago · Santiago Trujillo Relatório

0

You can keep a list of the delimiters, ordered by their value. Then, you can combine re.split with re.findall to only use delimiters produced from the latter that are the least valuable in the split, per the ranking in ops:

import re
def split_order(s):
   r, ops = re.findall('(?<=\s)and(?=\s)|\&|\-', s), ['and', '&', '-']
   m = -1 if not r else min([ops.index(i) for i in r])
   a, *b = re.split('|'.join(l:=[i for i in r if ops.index(i) == m]), s)
   return [s] if not l else ([a] if not b else [a, s[len(a)+len(l[0]):]])


vals = ['121 34 adsfd' , 'dsfsd and adfd', 'dsfsd & adfd' , 'dsfsd - adfd' , 'dsfsd and adfd and adsfa' , 'dsfsd and adfd - adsfa' , 'dsfsd - adfd and adsfa' ]
for i in vals:
   print(split_order(i))

Output:

['121 34 adsfd']
['dsfsd ', ' adfd']
['dsfsd ', ' adfd']
['dsfsd ', ' adfd']
['dsfsd ', ' adfd and adsfa']
['dsfsd ', ' adfd - adsfa']
['dsfsd - adfd ', ' adsfa']
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda