【问题标题】:How to iterate through a nested list or compound list to perform calculations for each list within the list in Python?如何遍历嵌套列表或复合列表以在 Python 中对列表中的每个列表执行计算?
【发布时间】:2021-12-14 07:21:14
【问题描述】:

我正在学习 Python,我正在尝试遍历在用户键入化学式时创建的化合物列表。例如,如果一个水分子的化学式是 H2O,那么化合物列表将是:

list = [
       ['H', 2],
       ['O', 1]
]

如果化合物葡萄糖的化学式为 C6H12O6,则化合物列表将为:

list = [
       ['C', 6],
       ['H', 12],
       ['O', 6]
]

我想遍历整个化合物列表并计算列表中每个元素的质量百分比并将它们显示给用户,无论用户输入多少元素。我的代码遇到的问题是当我尝试计算复合列表中每个元素的质量百分比时,它只提取列表中的最后一个元素并仅针对该元素执行计算。因此,当我为葡萄糖输入 C6H12O6 时,它只会对 O 或 Oxygen 执行计算,但我也想对 Carbon 和 Hydrogen 执行其他计算。我的函数计算质量百分比执行计算,但我不确定它是否适用于我想要完成的任务。我需要在函数中完成这一切,而其他函数必须保持原样。我也无法更改包含所有元素及其相关原子质量在函数 make 周期表中的非常长的字典。我真正可以更改的唯一函数是我的计算质量百分比函数以及它在 main() 函数中的调用方式。

这是我从化学式计算元素质量百分比的方法。在这个例子中,我得到了葡萄糖中碳的质量百分比。

将公式中每个元素的原子数求和为葡萄糖:

6 carbon atoms
12 hydrogen atoms
6 oxygen atoms

求每个元素的原子质量: 符号名称 原子质量

C       Carbon     12.0107
H       Hydrogen   1.00794
O       Oxygen     15.9994

将原子数乘以它们的原子质量:

6   ×   12.0107 =   72.0642
12  ×   1.00794 =   12.09528
6   ×   15.9994 =   95.9964

将乘法的结果相加得到葡萄糖的摩尔质量:

72.0642 + 12.09528 + 95.9964 = 180.15588 grams/mole

现在我们将得到葡萄糖中碳的质量百分比,而不是葡萄糖样品中的摩尔数:

72.0642 / 180.15588 = 0.40001026 or 40% 

因此,碳占葡萄糖质量的 40%。

这是我的程序代码。顺便说一句,我只知道如何用 Python 编写代码。非常感谢任何帮助。

ELEMENT_SYMBOL = 0
ATOMS = 1


def main():

    # Get a chemical formula for a molecule from the user.

    chemical_formula = input("Enter the molecular formula of the sample: ").title()
    
    # Get a mass in grams from the user.

    mass = float(input("Enter the mass in grams of the sample: "))



    # Call the make_periodic_table function and
    # store the periodic table in a variable.

    dictionary = make_periodic_table()


    # Call the parse_formula function to convert the
    # chemical formula given by the user to a compound
    # list that stores element symbols and the quantity
    # of atoms of each element in the molecule.

    element_group = parse_formula(chemical_formula, dictionary)
    

    # Call the compute_molar_mass function to compute the
    # molar mass of the molecule from the compound list.

    molar_mass = compute_molar_mass(element_group, dictionary)


    # Call the compute_mass_percentage function to compute the
    # mass percentage of the molecule from the compound list.

    mass_percent = compute_mass_percentage(element_group, dictionary)


    # Compute the number of moles of the sample.

    moles = mass / molar_mass

    # Print the molar mass.

    print(f"{molar_mass:.5f} grams/mole")

    # Print the number of moles.

    print(f"{moles:.5f} moles")

    print(parse_formula(chemical_formula, dictionary))

    print(f"{mass_percent}")
    
    

    
    
def make_periodic_table():
    
    table = {
            "Ac":   ["Actinium",        227],
            "Ag":   ["Silver",          107.8682],
            "Al":   ["Aluminum",        26.9815386],
            "Am":   ["Americium",       243],
            "Ar":   ["Argon",           39.948],
            "As":   ["Arsenic",         74.9216],
            "At":   ["Astatine",        210],
            "Au":   ["Gold",            196.966569],
            "B":    ["Boron",           10.811],
            "Ba":   ["Barium",          137.327],
            "Be":   ["Beryllium",       9.012182],
            "Bh":   ["Bohrium",         272],
            "Bi":   ["Bismuth",         208.9804],
            "Bk":   ["Berkelium",       247],
            "Br":   ["Bromine",         79.904],
            "C":    ["Carbon",          12.0107],
            "Ca":   ["Calcium",         40.078],
            "Cd":   ["Cadmium",         112.411],
            "Ce":   ["Cerium",          140.116],
            "Cf":   ["Californium",     251],
            "Cl":   ["Chlorine",        35.453],
            "Cm":   ["Curium",          247],
            "Cn":   ["Copernicium",     285],
            "Co":   ["Cobalt",          58.933195],
            "Cr":   ["Chromium",        51.9961],
            "Cs":   ["Cesium",          132.9054519],
            "Cu":   ["Copper",          63.546],
            "Db":   ["Dubnium",         268],
            "Ds":   ["Darmstadtium",    281],
            "Dy":   ["Dysprosium",      162.5],
            "Er":   ["Erbium",          167.2590],
            "Es":   ["Einsteinium",     252],
            "Eu":   ["Europium",        151.964],
            "F":    ["Fluorine",        18.9984032],
            "Fe":   ["Iron",            55.845],
            "Fl":   ["Flerovium",       289],
            "Fm":   ["Fermium",         257],
            "Fr":   ["Francium",        223],
            "Ga":   ["Gallium",         69.723],
            "Gd":   ["Gadolinium",      157.25],
            "Ge":   ["Germanium",       72.64],
            "H":    ["Hydrogen",        1.00794],
            "He":   ["Helium",          4.002602],
            "Hf":   ["Hafnium",         178.49],
            "Hg":   ["Mercury",         200.59],
            "Ho":   ["Holmium",         164.93032],
            "Hs":   ["Hassium",         270],
            "I":    ["Iodine",          126.90447],
            "In":   ["Indium",          114.818],
            "Ir":   ["Iridium",         192.217],
            "K":    ["Potassium",       39.0983],
            "Kr":   ["Krypton",         83.798],
            "La":   ["Lanthanum",       138.90547],
            "Li":   ["Lithium",         6.941],
            "Lr":   ["Lawrencium",      262],
            "Lu":   ["Lutetium",        174.9668],
            "Lv":   ["Livermorium",     293],
            "Mc":   ["Moscovium",       288],
            "Md":   ["Mendelevium",     258],
            "Mg":   ["Magnesium",       24.305],
            "Mn":   ["Manganese",       54.938045],
            "Mo":   ["Molybdenum",      95.96],
            "Mt":   ["Meitnerium",      276],
            "N":    ["Nitrogen",        14.0067],
            "Na":   ["Sodium",          22.98976928],
            "Nb":   ["Niobium",         92.90638],
            "Nd":   ["Neodymium",       144.242],
            "Ne":   ["Neon",            20.1797],
            "Nh":   ["Nihonium",        284],
            "Ni":   ["Nickel",          58.6934],
            "No":   ["Nobelium",        259],
            "Np":   ["Neptunium",       237],
            "O":    ["Oxygen",          15.9994],
            "Og":   ["Oganesson",       294],
            "Os":   ["Osmium",          190.23],
            "P":    ["Phosphorus",      30.973762],
            "Pa":   ["Protactinium",    231.03588],
            "Pb":   ["Lead",            207.2],
            "Pd":   ["Palladium",       106.42],
            "Pm":   ["Promethium",      145],
            "Po":   ["Polonium",        209],
            "Pr":   ["Praseodymium",    140.90765],
            "Pt":   ["Platinum",        195.084],
            "Pu":   ["Plutonium",       244],
            "Ra":   ["Radium",          226],
            "Rb":   ["Rubidium",        85.4678],
            "Re":   ["Rhenium",         186.207],
            "Rf":   ["Rutherfordium",   267],
            "Rg":   ["Roentgenium",     280],
            "Rh":   ["Rhodium",         102.9055],
            "Rn":   ["Radon",           222],
            "Ru":   ["Ruthenium",       101.07],
            "S":    ["Sulfur",          32.065],
            "Sb":   ["Antimony",        121.76],
            "Sc":   ["Scandium",        44.955912],
            "Se":   ["Selenium",        78.96],
            "Sg":   ["Seaborgium",      271],
            "Si":   ["Silicon",         28.0855],
            "Sm":   ["Samarium",        150.36],
            "Sn":   ["Tin",             118.71],
            "Sr":   ["Strontium",       87.62],
            "Ta":   ["Tantalum",        180.94788],
            "Tb":   ["Terbium",         158.92535],
            "Tc":   ["Technetium",      98],
            "Te":   ["Tellurium",       127.6],
            "Th":   ["Thorium",         232.03806],
            "Ti":   ["Titanium",        47.867],
            "Tl":   ["Thallium",        204.3833],
            "Tm":   ["Thulium",         168.93421],
            "Ts":   ["Tennessine",      294],
            "U":    ["Uranium",         238.02891],
            "V":    ["Vanadium",        50.9415],
            "W":    ["Tungsten",        183.84],
            "Xe":   ["Xenon",           131.293],
            "Y":    ["Yttrium",         88.90585],
            "Yb":   ["Ytterbium",       173.054],
            "Zn":   ["Zinc",            65.38],
            "Zr":   ["Zirconium",       91.224]
    }

    return table


class FormulaError(ValueError):
    """FormulaError is the type of error that
    parse_formula will raise if a formula is invalid.
    """
    pass


def parse_formula(formula, periodic_table_dict):
    """Convert a chemical formula for a molecule into a compound list
    that stores the quantity of atoms of each element in the molecule.
    For example, this function will convert "H2O" to [["H", 2], ["O", 1]]
    and "PO4H2(CH2)12CH3" to [["P", 1], ["O", 4], ["H", 29], ["C", 13]]
    """
    def parse_quant(formula, index):
        quant = 1
        if index < len(formula) and formula[index].isdecimal():
            start = index
            index += 1
            while index < len(formula) and formula[index].isdecimal():
                index += 1
            quant = int(formula[start:index])
        return quant, index

    def get_quant(elems, symbol):
        return 0 if symbol not in elems else elems[symbol]

    def parse_r(formula, index, level):
        start_index = index
        start_level = level
        elem_dict = {}
        while index < len(formula):
            ch = formula[index]
            if ch == "(":
                group_dict, index = parse_r(formula, index+1, level+1)
                quant, index = parse_quant(formula, index)
                for symbol in group_dict:
                    prev = get_quant(elem_dict, symbol)
                    elem_dict[symbol] = prev + group_dict[symbol] * quant
            elif ch.isalpha():
                symbol = formula[index:index+2]
                if symbol in periodic_table_dict:
                    index += 2
                else:
                    symbol = formula[index:index+1]
                    if symbol in periodic_table_dict:
                        index += 1
                    else:
                        raise FormulaError(
                            "invalid formula, unknown element symbol:",
                            formula, index)
                quant, index = parse_quant(formula, index)
                prev = get_quant(elem_dict, symbol)
                elem_dict[symbol] = prev + quant
            elif ch == ")":
                if level == 0:
                    raise FormulaError(
                        "invalid formula, unmatched close parenthesis:",
                        formula, index)
                level -= 1
                index += 1
                break
            else:
                if ch.isdecimal():
                    # Decimal digit not preceded by an
                    # element symbol or close parenthesis
                    message = "invalid formula:"
                else:
                    # Illegal character: [^()0-9a-zA-Z]
                    message = "invalid formula, illegal character:"
                raise FormulaError(message, formula, index)
        if level > 0 and level >= start_level:
            raise FormulaError(
                "invalid formula, unmatched open parenthesis:",
                formula, start_index - 1)
        return elem_dict, index

    # Return the compound list of element symbols and
    # quantities. Each element in the compound list
    # will be a list in this form: ["symbol", quantity]
    elem_dict, _ = parse_r(formula, 0, 0)
    return list(elem_dict.items())


# These are the indexes of the
# elements in the periodic table.
NAME_INDEX = 0
ATOMIC_MASS_INDEX = 1


def compute_molar_mass(symbol_quantity_list, periodic_table_dict):
    """Compute and return the total molar mass of all the
    elements listed in symbol_quantity_list. Each element in
    symbol_quantity_list is a list in the form: ["symbol", quantity].

    As an example, if symbol_quantity_list is [["H", 2], ["O", 1]],
    this function will calculate and return
    atomic_mass("H") * 2 + atomic_mass("O") * 1
    1.00794 * 2 + 15.9994 * 1
    18.01528
    """


    total_mass = 0.0
    
    for element in symbol_quantity_list:
        symbol = element[ELEMENT_SYMBOL]
        quantity = element[ATOMS]
        atomic_mass = periodic_table_dict[symbol][ATOMIC_MASS_INDEX]
        total_mass += atomic_mass * quantity
    
    return total_mass
        
    # For each element in the symbol_quantity_list:
    #   Split the element into symbol and quantity.
    #   Get the atomic mass for the symbol.
    #   Multiply the atomic mass by the quantity.
    #   Add the product into the total mass.

def compute_mass_percentage(symbol_quantity_list, periodic_table_dict):

    total_mass = 0.0
    mass_percent = 0.0
    
    for element in symbol_quantity_list:
        symbol = element[ELEMENT_SYMBOL]
        quantity = element[ATOMS]
        atomic_mass = periodic_table_dict[symbol][ATOMIC_MASS_INDEX]
        element_mass = quantity * atomic_mass
        total_mass += atomic_mass * quantity
        mass_percent = element_mass / total_mass
    
    return mass_percent


if __name__ == "__main__":
    main()

【问题讨论】:

标签: python-3.x dictionary for-loop iteration nested-lists


【解决方案1】:

我的代码遇到的问题是,当我尝试计算复合列表中每个元素的质量百分比时,它只提取列表中的最后一个元素并仅针对该元素执行计算。

你错了——这不是问题所在。它按应有的方式对列表中的每个元素执行计算。您只是未能存储结果,因此在每个后续循环周期中,先前的结果被覆盖,最后只返回最后一个结果。为了更正这一点并解释total_mass 在最后一次计算完成之前不正确的事实,您可以更改

    mass_percent = 0.0
    …
        mass_percent = element_mass / total_mass
    
    return mass_percent

    masses = []
    …
        masses += [element_mass]
    return [element_mass / total_mass for element_mass in masses]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-02-07
    • 2020-08-17
    • 2023-03-25
    • 2012-09-19
    • 2012-11-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多