列表推导式求和出现重复元素:与嵌套for循环结果不一致的解决咨询
问题:列表推导式求和出现重复元素,嵌套循环结果正常
需要生成表达式 (-2.0*EM*EX*W_1_M_X*x1/F - 2.0*EN*EX*W_1_N_X*x1/F),使用嵌套for循环计算的asum结果正确,但用列表推导式求和得到的aasum结果是目标值的2倍,存在重复元素累加的问题。
原代码如下:
import sympy as sp anions = {'X': 1 } cations = {'M': 1, 'N': 1} neutrals = {'1' : 0} aa = list(-(1 / sp.symbols(f'F')) * sp.symbols(f'E{m}') * sp.symbols(f'E{n}') * \ ((x + y) / (x * y)) * sp.symbols(f'x{str(list(neutrals.keys())[0])}') * sp.symbols(f'W_{str(list(neutrals.keys())[0])}_{str(m)}_{str(n)}') \ for m in cations.keys() \ for x in cations.values() \ for n in anions.keys() \ for y in anions.values()) aasum = sum(aa) asum = 0.0 for k in anions: for j in cations: for n in neutrals: asum += -(1 / sp.symbols(f'F')) * sp.symbols(f'E{str(j)}') * sp.symbols(f'E{str(k)}') * \ ((cations[j] + anions[k]) / (cations[j] * anions[k])) * sp.symbols(f'x{str(list(neutrals.keys())[0])}') *\ sp.symbols(f'W_{str(list(neutrals.keys())[0])}_{str(j)}_{str(k)}') print(asum,'...', aasum)
运行结果:
asum:-2.0*EM*EX*W_1_M_X*x1/F - 2.0*EN*EX*W_1_N_X*x1/F ... aasum:-4.0*EM*EX*W_1_M_X*x1/F - 4.0*EN*EX*W_1_N_X*x1/F
问题原因
原列表推导式中,循环顺序是先遍历阳离子的键,再遍历阳离子的所有值,接着遍历阴离子的键,最后遍历阴离子的所有值。cations.values()有2个元素(均为1),anions.values()有1个元素(1),这导致每个(m,n)键组合会被重复计算2次(每个阳离子值对应一次),最终求和结果翻倍。而嵌套循环中是通过键直接获取对应的值,每个(j,k)组合只计算一次,结果正确。
修正方案
不要单独遍历values,而是在遍历keys的同时,通过键获取对应的值,确保每个键值对只处理一次。修正后的列表推导式如下:
import sympy as sp anions = {'X': 1 } cations = {'M': 1, 'N': 1} neutrals = {'1' : 0} # 修正后的列表推导式:遍历键的同时获取对应的值 aa = list(-(1 / sp.symbols(f'F')) * sp.symbols(f'E{m}') * sp.symbols(f'E{n}') * \ ((cations[m] + anions[n]) / (cations[m] * anions[n])) * sp.symbols(f'x{str(list(neutrals.keys())[0])}') * sp.symbols(f'W_{str(list(neutrals.keys())[0])}_{str(m)}_{str(n)}') \ for m in cations.keys() \ for n in anions.keys()) aasum = sum(aa) asum = 0.0 for k in anions: for j in cations: for n in neutrals: asum += -(1 / sp.symbols(f'F')) * sp.symbols(f'E{str(j)}') * sp.symbols(f'E{str(k)}') * \ ((cations[j] + anions[k]) / (cations[j] * anions[k])) * sp.symbols(f'x{str(list(neutrals.keys())[0])}') *\ sp.symbols(f'W_{str(list(neutrals.keys())[0])}_{str(j)}_{str(k)}') print(asum,'...', aasum)
运行修正后的代码,aasum和asum结果一致,均为目标表达式。
内容的提问来源于stack exchange,提问作者user19396094
相关产品推荐
相关产品推荐

