【问题标题】:How to iterate over a dictionary and operate with its elements?如何遍历字典并对其元素进行操作?
【发布时间】:2019-04-01 05:01:26
【问题描述】:

我有这本字典,其中键代表原子类型,值代表原子质量:

mass = {'H': 1.007825, 'C': 12.01, 'O': 15.9994, 'N': 14.0067, 'S': 31.972071,
        'P': 30.973762}

我想做的是创建一个给定分子的函数,例如('H2-N-C6-H4-C-O-2H'),迭代mass 字典并计算给定分子的原子质量。质量值必须乘以原子类型后面的数字:H2 = H.value * 2

我知道首先我必须隔离给定分子的键,为此我可以使用string.split('-')。然后,如果给定分子的键在字典中,我想我可以使用和if 块来确定要完成的条件。但后来我迷失了我应该如何继续找到字典每个键的质量。

预期的结果应该是这样的:

mass_counter('H2-N15-P3')

out[0] 39351.14

我该怎么做?

编辑:

这是我迄今为止尝试过的

# Atomic masses
mass = {'H': 1.007825, 'C': 12.01, 'O': 15.9994, 'N': 14.0067, 'S': 31.972071, 
        'P': 30.973762}

def calculate_atomic_mass(molecule):
    """
    Calculate the atomic mass of a given molecule
    """
    mass = 0.0
    mol = molecule.split('-')

    for key in mass:
        if key in mol:
            atom = key

    return mass

print calculate_atomic_mass('H2-O')
print calculate_atomic_mass('H2-S-O4')
print calculate_atomic_mass('C2-H5-O-H')
print calculate_atomic_mass('H2-N-C6-H4-C-O-2H')

【问题讨论】:

  • 你能展示你已经尝试过的吗?
  • 对了H前面2在做什么?
  • 'H2-N15-P3': 1*2 + 14*15 + 31*3 = 305
  • 你为什么要倍增群众?
  • 与其检查“分子”中的每个可能元素,然后必须弄清楚有多少这样的原子,并担心会出现多次出现,不如反过来做:除以@ 987654332@,获取元素和数字,通过简单地索引字典以元素为键masses[element]来获取质量。

标签: python python-2.7 loops dictionary


【解决方案1】:

鉴于所有组件都具有Aa123 的形状,这里使用正则表达式可能更容易识别部分,例如:

import re
srch = re.compile(r'([A-Za-z]+)(\d*)')
mass = {'H': 1.007825, 'C': 12.01, 'O': 15.9994, 'N': 14.0067, 'S': 31.972071, 'P': 30.973762}

def calculate_atomic_mass(molecule):
    return sum(mass[a[1]]*int(a[2] or '1') for a in srch.finditer(molecule))

这里我们的regular expression [wiki] 捕获了[A-Z-a-z]s 的序列,和一个(可能为空的)数字序列(\d*),它们分别是第一个和第二个捕获组,因此可以获得匹配a[1]a[2]

然后产生:

>>> print(calculate_atomic_mass('H2-O'))
18.01505
>>> print(calculate_atomic_mass('H2-S-O4'))
97.985321
>>> print(calculate_atomic_mass('C2-H5-O-H'))
46.06635
>>> print(calculate_atomic_mass('H2-N-C6-H4-C-O-2H'))
121.130875
>>> print(calculate_atomic_mass('H2-N15-P3'))
305.037436

因此,我们将第一个捕获组的 mass[..](原子名称)乘以末尾的数字之和,如果找不到这样的数字,我们使用 '1'

或者我们可以先拆分数据,然后找一个原子部分和一个数字部分:

import re
srch = re.compile(r'^([A-Za-z]+)(\d*)$')

def calculate_atomic_mass(molecule):
    """
    Calculate the atomic mass of a given molecule
    """
    result = 0.0
    mol = molecule.split('-')
    if atm in mol:
        c = srch.find(atm)
        result += result[c[1]] * int(c[2] or '1')
    return result

【讨论】:

  • 您好威廉,非常感谢您的回答。我对regex 不太了解,请提供一些关于re.compile 部分在做什么的额外解释?非常感谢
【解决方案2】:

这是一个没有正则表达式的答案:

import string
# Atomic masses
masses = {'H': 1.007825, 'C': 12.01, 'O': 15.9994, 'N': 14.0067, 'S': 31.972071, 
        'P': 30.973762}

def calculate_atomic_mass(molecule):
    """
    Calculate the atomic mass of a given molecule
    """
    mass = 0.0
    for key in molecule.split('-'):
        # check if any number is available
        if not key[-1] in string.digits:
            el, n = key, 1
        # check length of element label (1 or 2)
        elif key[1] in string.digits:
            el, n = key[:1], int(key[1:])
        else:
            el, n = key[:2], int(key[2:])
        mass += masses[el]*n
    return mass

print calculate_atomic_mass('H2-O')
print calculate_atomic_mass('H2-S-O4')
print calculate_atomic_mass('C2-H5-O-H')
print calculate_atomic_mass('H2-N-C6-H4-C-O-H2')

【讨论】:

  • 谢谢Feodoran,这是一个很好的方法。了解这样做的不同方法很好:)
【解决方案3】:

我会这样做。你真的不需要遍历字典。相反,您需要遍历分子中的原子并(随机)在字典中查找内容。

这里有一个例子,它假设构成分子的任何种类的原子永远不会超过 10 个,并且每个元素的名称只有一个字母长。

# Atomic masses.
MASSES = {'H': 1.007825, 'C': 12.01, 'O': 15.9994, 'N': 14.0067, 'S': 31.972071,
          'P': 30.973762}

def calculate_atomic_mass(molecule):
    """ Calculate the atomic mass of a given molecule. """
    mass = 0.0
    for atom in molecule.split('-'):
        if len(atom) == 1:
            mass += MASSES[atom]
        else:
            atom, count = atom[0], atom[1]
            mass += MASSES[atom] * int(count)

    return mass

print calculate_atomic_mass('H2-O')               # -> 18.01505
print calculate_atomic_mass('H2-S-O4')            # -> 97.985321
print calculate_atomic_mass('C2-H5-O-H')          # -> 46.06635
print calculate_atomic_mass('H2-N-C6-H4-C-O-H2')  # -> 122.1387

【讨论】:

  • 您还假设所有元素标签的长度为 1。对于此处给出的示例,这是正确的,但不是一般的。
  • @Feodoran:没错,但基本思想仍然成立。要处理最一般的情况,需要更复杂的解析(可能通过正则表达式)。我只包括了可以解决所发布问题的最低限度(并解决有关如何迭代字典的名义问题)。
  • 嗨,Martineau,没关系,我明白了 ;)
  • Miguel:谢谢……很高兴听到。问题RegEx for parsing chemical formulas 应该有助于用正则表达式解析它们(这是@Feodoran 答案中的替代方法)。
猜你喜欢
  • 2014-01-24
  • 2018-02-03
  • 2021-04-21
  • 2018-08-18
  • 2020-07-10
  • 2019-10-26
  • 1970-01-01
  • 1970-01-01
  • 2020-01-25
相关资源
最近更新 更多