【问题标题】:Python: Extracting Information from ParenthesisPython:从括号中提取信息
【发布时间】:2014-07-06 20:19:03
【问题描述】:

我目前有 10 个人,从 AK。他们的每个分数都插入到玩家姓名之后,例如A(12)F(99)

例如,我目前的足球队名单是这样的:

A(14)B(12)C(9)D(16)E(14)F(23)G(25)H(12)I(3)JK(14).

在本例中,J 没有分数。 (如你所知,我没有练习太多。如果你能看到这一点,杰夫,请多练习。就是你。:D)

从此列表中提取信息到一个新列表中

scores=['A', 14, 'B', 12, 'C', 9, ...]

现在,从最高到最低打印分数,在第一个之后打印(Gold),在第二个之后打印(Silver),在第三个之后打印(Bronze),依此类推。相同的分数可以按任意顺序打印。

G: 25 (Gold)
F: 23 (Silver)
D: 16 (Bronze)
A: 14 
E: 14
etc.

谢谢,如果这篇文章没有帮助,请告诉我如何改进。

我已经试过了

>>> re.split("[()]", 'A(14)B(12)C(9)D(16)E(14)F(23)G(25)H(12)I(3)JK(14)')

这给了我

['A', '14', 'B', '12', 'C', '9', 'D', '16', 'E', '14', 'F', '23', 'G', '25', 'H', '12', 'I', '3', 'JK', '14', '']

我喜欢这个,但是,JK 在一起。请帮忙。

【问题讨论】:

  • 到目前为止你有什么尝试?
  • 请添加您对解决方案的尝试...这不是家庭作业服务,我们希望您先努力
  • 这确实是多个问题。第一个(也是最复杂的,取决于您的观点)是从文本数据中提取分数。之后对分数的操作是另一回事。
  • re.split("[()]",my_text) 可能对第一部分有所帮助......或者它可能不会......
  • 对于 Strikeskids,我已经完全按照 Joran Beasley 的建议尝试了 :)

标签: python regex string split


【解决方案1】:

我会使用不同的正则表达式,它为您提供单独的 (name, count) 对:

import re

re.findall(r'([A-Z])(?:\((\d+)\))?', inputtext)

这会在A-Z 范围内查找一个字母(为扩展留出空间),可选(?:..)?)后跟括号中的数字(\(\) 是文字括号,\d+ 是 1 个或多个数字)。

re.findall() 生成字符串中所有匹配项的列表,每个匹配项都是模式中两组的元组(每个 (...) 封闭模式),因此字母后跟分数(或空字符串,对于J):

>>> import re
>>> inputtext = 'A(14)B(12)C(9)D(16)E(14)F(23)G(25)H(12)I(3)JK(14).'
>>> re.findall(r'([A-Z])(?:\((\d+)\))?', inputtext)
[('A', '14'), ('B', '12'), ('C', '9'), ('D', '16'), ('E', '14'), ('F', '23'), ('G', '25'), ('H', '12'), ('I', '3'), ('J', ''), ('K', '14')]

这些对比在一个平面列表中任意组合字母和数字要实用得多;您的数字现在已与您的字母配对。

然后可以将每一对用于输入collections.Counter() object,这可以方便您进行排序:

from collections import Counter

points = Counter({name: int(count or 0) 
                  for name, count in re.findall(r'([A-Z])(?:\((\d+)\))?', inputtext)})

接下来,给出排名的映射:

ranks = {0: '(Gold)', 1: '(Silver)', 2: '(Bronze)'}

最后循环Counter.most_common() 以按计数降序排序,并与enumerate() 一起提供排名:

for i, (name, score) in enumerate(points.most_common()):
    print '{}: {} {}'.format(name, score, ranks.get(i, ''))

演示:

>>> import re
>>> from collections import Counter
>>> inputtext = 'A(14)B(12)C(9)D(16)E(14)F(23)G(25)H(12)I(3)JK(14).'
>>> re.findall(r'([A-Z])(?:\((\d+)\))?', inputtext)
[('A', '14'), ('B', '12'), ('C', '9'), ('D', '16'), ('E', '14'), ('F', '23'), ('G', '25'), ('H', '12'), ('I', '3'), ('J', ''), ('K', '14')]
>>> points = Counter({name: int(count or 0) 
...                   for name, count in re.findall(r'([A-Z])(?:\((\d+)\))?', inputtext)})
>>> points
Counter({'G': 25, 'F': 23, 'D': 16, 'A': 14, 'E': 14, 'K': 14, 'B': 12, 'H': 12, 'C': 9, 'I': 3, 'J': 0})
>>> ranks = {0: '(Gold)', 1: '(Silver)', 2: '(Bronze)'}
>>> for i, (name, score) in enumerate(points.most_common()):
...     print '{}: {} {}'.format(name, score, ranks.get(i, ''))
... 
G: 25 (Gold)
F: 23 (Silver)
D: 16 (Bronze)
A: 14 
E: 14 
K: 14 
B: 12 
H: 12 
C: 9 
I: 3 
J: 0 

【讨论】:

    【解决方案2】:

    只需像这样将JK() 替换为J(0)K()。它使用积极的前瞻性。见here

    inputtext = 'A(14)B(12)C(9)D(16)E(14)F(23)G(25)H(12)I(3)JK(14).'
    inputtext = re.sub(r"([A-Z])(?=[^(])", r"\1(0)", inputtext)
    

    你也可以像这样删除J本身。

    inputtext = re.sub(r"([A-Z])(?=[^(])", r"", inputtext)
    

    好的。然后就可以随心所欲了。

    【讨论】:

      猜你喜欢
      • 2020-01-25
      • 2012-01-26
      • 2020-09-23
      • 1970-01-01
      • 1970-01-01
      • 2012-12-26
      • 1970-01-01
      • 1970-01-01
      • 2017-12-23
      相关资源
      最近更新 更多