将列表中的整数乘以列表中的单词

3

我不确定如何将跟在字符串后面的数字乘以字符串。 我想找到化合物的相对分子质量(RMM),所以我先制作了一个RMM字典,然后将它们加在一起。 我遇到的问题是对于像H2O这样的化合物。

name = input("Insert the name of a molecule/atom to find its RMM/RAM: ")
compound = re.sub('([A-Z])', r' \1', name)
Compound = compound.split(' ')
r = re.split('(\d+)', compound)

例如:

When name = H2O
Compound = ['', 'H2', 'O']
r = ['H', '2', 'O']

我希望将2乘以H得出一个值"['H', 'H', 'O']"。
简而言之:我想要在列表中的名称后打印出整数,这个整数代表了前面列出的对象需要打印的数量(例如:[O, 2] => O O, [C, O, 2] => C O O)。
这个问题可能有些复杂,请让我知道是否需要澄清。谢谢。
5个回答

3
在您定义了“compound”之后,以下是如何处理的:
test = re.findall('([a-zA-z]+)(\d*)', compound)
expand = [a*int(b) if len(b) > 0 else a for (a, b) in test]

匹配一个或多个实例的字母,后跟可选数量的数字——如果没有数字,我们只返回字母;如果有数字,我们将相应的字母复制相应次数。这不完全返回你期望的结果——它会返回['HH', 'O'] - 因此,请告诉我是否符合要求。
注:假设您的化合物使用由单个大写字母或单个大写字母后跟小写字母的数量构成的元素,则可以添加以下内容:
final = re.findall('[A-Z][a-z]*', ''.join(expand))

这将把您的元素作为单独的条目返回到列表中,例如['H', 'H', 'O']

编辑2:在我的上一个编辑假设下,我们实际上可以将整个过程缩减为只有几行:

name = raw_input("Insert the name of a molecule/atom to find its RMM/RAM: ")
test = re.findall('([A-z][a-z]*)(\d*)', name)
final = re.findall('[A-Z][a-z]*', ''.join([a*int(b) if len(b) > 0 else a for (a, b) in test]))

你可以使用类似 [char for charGroup in ['HH', 'O'] for char in charGroup] 的方法来展开结果列表,输出 ['H', 'H', 'O'] - evan.oman

2

你可以尝试像这样做...


(可能是关于IT技术方面的建议或提示)
compound = 'h2o' 
final = []
for x in range(len(compound)):
    if compound[x].isdigit() and x != 0:
        for count in range(int(compound[x])-1):
            final.append(compound[x-1])
    else:
       final.append(compound[x])

compound[x] != '0' 的检查是多余的。此外,对于错误的输入 final.append(compund[x-1]) 将会引发异常。 - Aditya
你是正确的。改成 x!=0 应该能消除不良输入的可能性。 - SarTheFirst

1
使用正则表达式和生成器函数:
import re

def multilpy_string(seq):
    regex = re.compile("([a-zA-Z][0-9])|([a-zA-Z])")
    for alnum, alpha in regex.findall(''.join(seq)):
        if alnum:
            for char in alnum[0] * int(alnum[1]):
                yield char
        else:
            yield alpha

l = ['C', 'O', '2'] # ['C', 'O', 'O']
print(list(multilpy_string(l)))

我们使用''.join将您的列表重新组合。然后,我们编译一个正则表达式模式,它匹配您列表中的两种字符串类型。如果字符串是一个字母,并且后面跟着一个数字,则将其放入一组中。如果它是单个数字,则将其放入自己的组中。然后,我们遍历每个组。如果我们在一个组中找到了东西,我们就会产生正确的值。

1

以下是几个嵌套的for循环综合句子,用两行代码就能完成:

In [1]: groups = [h*int(''.join(t)) if len(t) else h for h, *t in re.findall('[A-Z]\d*', 'H2O')]

In[2]: [c for cG in groups for c in cG]
Out[2]: ['H', 'H', 'O']

注意:我正在拆解和重构字符串,因此这可能不是最有效的方法。
以下是一个更长的示例:
In [2]: def findElements(molecule):
    ...:      groups = [h*int(''.join(t)) if len(t) else h for h, *t in re.findall('[A-Z]\d*', molecule)]
    ...:      return [c for cG in groups for c in cG]

In [3]: findElements("H2O5S7D")
Out[3]: ['H', 'H', 'O', 'O', 'O', 'O', 'O', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'D']

你假设元素仅由大写字母组成并且(我认为)正在使用Python 3。 - asongtoruin
是的,只有大写字母,但快速的 [A-Z][a-z]? 就可以解决这个问题。我会更新,但你的答案已经更好了(使用元组展开而不是我的头/尾匹配)。 - evan.oman

-1
在Python3中(我不知道Python2),您可以简单地将字符串相乘。
例如:
print("H"*2) # HH
print(2*"H") # HH

证明这些信息有用的方法:

r = ['H', '2', 'O']
replacements = [(index, int(ch)) for index, ch in enumerate(r) if ch.isdigit()]

for postion, times in replacements:
    r[postion] = (times - 1) * r[postion - 1]

# flaten the result
r = [ch for s in r for ch in s]

print(r) # ['H', 'H', 'O']

这并不完全回答了问题。你可能需要再读一遍,以更好地理解Gad在问什么。 - Christian Dean
哇,我发帖不到30秒就收到了一个负评。对你的快速判断能力感到印象深刻;-) - shaman-apprentice
这并不是一个直接的答案,但在我看来它很有用。 - shaman-apprentice
请不要误解我的意思 :) 我认为你只是误解了问题。正如我在之前的评论中所说,再读一遍问题,看看你哪里错了。祝好! - Christian Dean
在我看来,答案不一定要给出完整的解决方案(我总是很高兴得到一些提示和新知识! :))但是我为您添加了一个完整的解决方案作为证明,证明我的答案是有用的 ;) (我第一次就理解了问题;也许您应该在决定投票反对并在最多30秒内写下反对原因之前再仔细考虑一下我的答案 ;P) - shaman-apprentice
1
踩票是匿名的,所以你无法确定谁踩了你的回答。但我要说这次是我踩了你的回答。我认为有时候为什么要踩某些东西提供清晰度是很重要的。 - Christian Dean

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接