python输入逗号分隔_关于python:如何用括号外的逗号分割字符串?

我得到了这样的格式的字符串:

1"Wilbur Smith (Billy, son of John), Eddie Murphy (John), Elvis Presley, Jane Doe (Jane Doe)"

因此从根本上讲,它是演员姓名的列表(可选地,其后是括号中的角色)。 角色本身可以包含逗号(演员的名字不能,我强烈希望如此)。

我的目标是将此字符串拆分为成对的列表-(actor name, actor role)。

一个显而易见的解决方案是遍历每个字符,检查'(',')'和','的出现情况,并在出现逗号时将其拆分。 但这似乎有点沉重...

我正在考虑使用正则表达式拆分它:首先用括号将字符串拆分:

1

2

3

4import re

x ="Wilbur Smith (Billy, son of John), Eddie Murphy (John), Elvis Presley, Jane Doe (Jane Doe)"

s = re.split(r'[()]', x)

# ['Wilbur Smith ', 'Billy, son of John', ', Eddie Murphy ', 'John', ', Elvis Presley, Jane Doe ', 'Jane Doe', '']

这里的奇数元素是演员名称,甚至是角色。 然后我可以用逗号分隔名称,并以某种方式提取名称角色对。 但是,这似乎比我的第一种方法还要糟糕。

是否有任何更简单/更好的方法来执行此操作,而只需一个正则表达式或一段不错的代码?

一种方法是将findall与正则表达式一起使用,该正则表达式贪婪地匹配分隔符之间可能会发生的事情。例如:

1

2

3

4>>> s ="Wilbur Smith (Billy, son of John), Eddie Murphy (John), Elvis Presley, Jane Doe (Jane Doe)"

>>> r = re.compile(r'(?:[^,(]|\([^)]*\))+')

>>> r.findall(s)

['Wilbur Smith (Billy, son of John)', ' Eddie Murphy (John)', ' Elvis Presley', ' Jane Doe (Jane Doe)']

上面的正则表达式匹配一个或多个:

非逗号,非开放字符

以开放括号开头的字符串,包含0个或多个非封闭括号,然后是封闭括号

关于此方法的一个怪癖是将相邻的分隔符视为单个分隔符。也就是说,您不会看到一个空字符串。根据您的用例,这可能是错误或功能。

还要注意,正则表达式不适用于可能嵌套的情况。因此,例如,这将错误地拆分:

1"Wilbur Smith (son of John (Johnny, son of James), aka Billy), Eddie Murphy (John)"

如果您需要处理嵌套,则最好的选择是将字符串分成括号,逗号和其他所有内容(本质上是对其进行标记化-这部分仍可以使用正则表达式来完成),然后遍历这些标记重新组合字段,并保持跟踪嵌套级别(正则表达式无法自行执行的嵌套级别跟踪)。

您可以通过匹配记录而不是分隔符立即将其分为几个字段:[(m.group(" name"),m.group(" role")))for re.findall("(?P 。+ ?)(?(?P [^] +)(, s * | $))",x)]

如果需要,可以为令牌解决方案+1。上下行走时弹出堆栈,这是一种经典的方法。

每当我看到正则表达式有用时,就像我这样,我就开始怀疑-它们是否是人类可读的?还是它只是我...乍看之下谁看不见?

好答案。谢谢劳伦斯!如果我想这样做但不在输出中括号内包含内容,该如何解决这个问题?

@ user815423426在这种情况下,Id可能使用的方法是对结果列表进行第二次传递并删除括号。例如:r = [re.sub(r\([^)]*\), , s) for s in r]之类的东西。如果您需要更详细的答案,则可能应该发布一个单独的问题。

1s = re.split(r',\s*(?=[^)]*(?:\(|$))', x)

先行匹配下一个开括号或字符串末尾的所有内容,前提是两者之间没有闭括号。这样可以确保逗号不在括号内。

我认为解决此问题的最佳方法是使用python内置的csv模块。

由于csv模块仅允许一个字符quotechar,因此您需要对输入进行替换以将()转换为类似|或"的字符。然后确保您使用的是适当的方言,然后离开。

尝试人类可读的正则表达式:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16import re

regex = re.compile(r"""

# name starts and ends on word boundary

# no '(' or commas in the name

(?P\b[^(,]+\b)

\s*

# everything inside parentheses is a role

(?:\(

(?P[^)]+)

\))? # role is optional

""", re.VERBOSE)

s = ("Wilbur Smith (Billy, son of John), Eddie Murphy (John), Elvis Presley,"

"Jane Doe (Jane Doe)")

print re.findall(regex, s)

输出:

1

2[('Wilbur Smith', 'Billy, son of John'), ('Eddie Murphy', 'John'),

('Elvis Presley', ''), ('Jane Doe', 'Jane Doe')]

可读的正则表达式-是不是矛盾词?

这篇文章对我有很大帮助。 我想用引号外的逗号分隔字符串。 我用它作为入门。 我的最后一行代码是regEx = re.compile(r'(?:[^,"]|"[^"]*")+')。 万分感谢。

这是我过去用于此类情况的通用技术:

将re模块的sub函数与函数作为替换参数一起使用。该函数跟踪打开和关闭括号,方括号和花括号以及单引号和双引号,并且仅在此类带括号和引号的子字符串之外执行替换。然后,您可以用您确定不会出现在字符串中的另一个字符替换无括号/带引号的逗号(我使用ASCII / Unicode组分隔符:chr(29)代码),然后执行一个简单的字符串。在那个角色上分裂。这是代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33import re

def srchrepl(srch, repl, string):

"""Replace non-bracketed/quoted occurrences of srch with repl in string"""

resrchrepl = re.compile(r"""(?P[([{])|(?P['"])|(?P["""

+ srch +"""])|(?P[)\]}])""")

return resrchrepl.sub(_subfact(repl), string)

def _subfact(repl):

"""Replacement function factory for regex sub method in srchrepl."""

level = 0

qtflags = 0

def subf(mo):

nonlocal level, qtflags

sepfound = mo.group('sep')

if sepfound:

if level == 0 and qtflags == 0:

return repl

else:

return mo.group(0)

elif mo.group('lbrkt'):

level += 1

return mo.group(0)

elif mo.group('quote') =="'":

qtflags ^= 1 # toggle bit 1

return"'"

elif mo.group('quote') == '"':

qtflags ^= 2 # toggle bit 2

return '"'

elif mo.group('rbrkt'):

level -= 1

return mo.group(0)

return subf

如果您的Python版本中没有nonlocal,只需将其更改为global并在模块级别定义level和qtflags。

使用方法如下:

1

2

3

4

5>>> GRPSEP = chr(29)

>>> string ="Wilbur Smith (Billy, son of John), Eddie Murphy (John), Elvis Presley, Jane Doe (Jane Doe)"

>>> lst = srchrepl(',', GRPSEP, string).split(GRPSEP)

>>> lst

['Wilbur Smith (Billy, son of John)', ' Eddie Murphy (John)', ' Elvis Presley', ' Jane Doe (Jane Doe)']

我的答案将不使用正则表达式。

我认为状态为in_actor_name的简单字符扫描程序应该可以工作。请记住,状态" in_actor_name"在此状态下以')'或逗号终止。

我的尝试:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22s = 'Wilbur Smith (Billy, son of John), Eddie Murphy (John), Elvis Presley, Jane Doe (Jane Doe)'

in_actor_name = 1

role = ''

name = ''

for c in s:

if c == ')' or (c == ',' and in_actor_name):

in_actor_name = 1

name = name.strip()

if name:

print"%s: %s" % (name, role)

name = ''

role = ''

elif c == '(':

in_actor_name = 0

else:

if in_actor_name:

name += c

else:

role += c

if name:

print"%s: %s" % (name, role)

输出:

1

2

3

4Wilbur Smith: Billy, son of John

Eddie Murphy: John

Elvis Presley:

Jane Doe: Jane Doe

被")"分割

1

2

3

4

5

6

7

8

9

10>>> s="Wilbur Smith (Billy, son of John), Eddie Murphy (John), Elvis Presley, Jane Doe (Jane Doe)"

>>> s.split(")")

['Wilbur Smith (Billy, son of John', ', Eddie Murphy (John', ', Elvis Presley, Jane Doe (Jane Doe', '']

>>> for i in s.split(")"):

... print i.split("(")

...

['Wilbur Smith ', 'Billy, son of John']

[', Eddie Murphy ', 'John']

[', Elvis Presley, Jane Doe ', 'Jane Doe']

['']

您可以进一步检查以获取()不附带的那些名称。

我当然同意以上@Wogan的观点,即使用CSV模块是一个好方法。话虽如此,如果您仍然想尝试使用正则表达式解决方案,请尝试一下,但是您必须将其适应Python方言

1string.split(/,(?=(?:[^"]*"[^"]*")*(?![^"]*"))/)

高温超导

如果您的数据中有任何错误或干扰,以上答案均不正确。

如果您每次都知道数据正确,那么很容易想到一个好的解决方案。但是,如果出现格式错误怎么办?你想发生什么?

假设有嵌套括号?假设括号不匹配?假设字符串以逗号结尾或以逗号开头,或者连续有两个?

以上所有解决方案都会产生或多或少的垃圾,并且不会向您报告。

由我自己决定,我将严格限制什么是"正确的"数据-在注释之前,之间或之后,没有嵌套括号,没有不匹配的括号,没有空段-随便验证,然后提出如果我无法验证,则为例外。

我们必须假设该问题包含我们需要回答的所有信息。因此,我们假设输入已经过验证,并且格式已经完整描述(例如,没有嵌套的括号)。如果这些假设中的任何一个被证明是错误的,则希望OP将来能够学会提出更好的问题。 ;)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值