7
votes

Python Regex - Attaches étrangères

Je veux diviser une chaîne en utilisant - , + = , == , = , + et espace blanc comme des délimiteurs. Je veux garder le délimiteur à moins que ce ne soit d'espace blanc.

J'ai essayé d'y parvenir avec le code suivant: xxx

Je m'attendais à ce que la sortie soit < / p> xxx

Cependant, j'ai obtenu xxx

qui est presque ce que je voulais, sauf qu'il y ait assez de Aucun S et Strings vides.

Pourquoi est-ce que cela se comporte de cette façon et comment puis-je le changer pour obtenir ce que je veux?


1 commentaires

Les chaînes vides sont parce que vous avez 2 caractères correspondants juste à côté de l'autre, alors lorsqu'il est séparé, ils ont un '' entre eux. C'est un peu intuitif avec des groupes de capture dans le mélange


5 Réponses :


1
votes

Ce modèle est plus aligné avec ce que vous voulez:

\s*(\-|\+\=|\=\=|\=|\+)\s*


1 commentaires

Cela ne cassera pas "bonjour là-bas" en deux jetons, que je crois que l'option est l'intention de l'utilisation de WhitSpace comme un délimiteur.



3
votes

re.split par défaut renvoie un tableau de la Bits de chaînes qui se trouvent entre les matchs: (comme @Laurence Gonsalves Notes, c'est son utilisation principale.)

def tokenize(s):
  import re
  pattern = re.compile("(\-|\+\=|\=\=|\=|\+)|\s+")
  return [ x for x in pattern.split(s) if x ]


1 commentaires

Notez que le retour des bits intermédiaires est en quelque sorte le «comportement principal», analogue à str.split. La chose de capture est en quelque sorte une caractéristique supplémentaire.



2
votes

Pourquoi est-ce que cela se comporte de cette façon?

Selon la documentation de re.split:

Si la capture de parenthèses est utilisée en motif, le texte de tous les groupes du motif est également renvoyé dans le cadre de la liste résultante.

Ceci est littéralement correct: si la capture de parenthèses est utilisée, le texte de tous les groupes est renvoyé, qu'ils soient ou non appariés; ceux qui ne correspondent rien de retour Aucun .

comme toujours avec Split , deux délimiteurs consécutifs sont considérés comme des chaînes vides séparées, de sorte que vous obtenez Les chaînes vides entrecoupées.

Comment puis-je le changer pour obtenir ce que je veux?

La solution la plus simple consiste à filtrer la sortie: < Pré> xxx


0 commentaires

0
votes

Essayez ceci:

def tokenize(s):
  import re
  pattern = re.compile("(\-|\+\=|\=\=|\=|\+)|\s+")
  x = pattern.split(s)
  result = []
  for item in x:
    if item != '' and item != None:
      result.append(item)
  return result

print(tokenize("hello-+==== =+  there"))


0 commentaires

2
votes

Peut-être re.findall serait plus approprié pour vous? XXX


2 commentaires

Une préoccupation que j'ai avec votre solution est que plus tard, je souhaite supporter plus de délimiteurs (par exemple, * , && ), et j'ai peur que le [^ - + = \ s] + une partie du motif sera plus compliqué.


Y a-t-il des règles sur les jetons qui ne sont pas des délimiteurs? Peut-être que vous pourriez utiliser, par exemple. \ w + au lieu de [^ - + = \ s] + .