单位符号的分数化简:结果错误



我正在写一个函数,用符号(如"kg")来简化分数,而不带数字(系数)。

函数接受两个实参:第一个列表包含分子中所引用的所有单位,第二个列表列出分母中所引用的单位。

我想我已经完成了大部分的功能,但是我不明白为什么它没有通过一些测试。

例如,当分母和分子相等时,它不会像预期的那样返回(['1'], ['1']),另一个例子是当测试中的函数返回(['1', '1', 's'], ['s'])而不是(['1'], ['1'])时。

我代码:

def canonical(unit):
numerador = unit[0]
denominador = unit[1]
numerador.sort()
denominador.sort()

lstNumerador = numerador
lstDenominador = denominador

for i in numerador:
for j in denominador:
if i == j:
lstNumerador.remove(i)
lstDenominador.remove(j)


if lstNumerador.count('1') > 0:
lstNumerador.remove('1')

if lstDenominador.count('1') > 0:
lstDenominador.remove('1')

if len(lstNumerador) == 0:
lstNumerador.append('1')

if len(lstDenominador) == 0:
lstDenominador.append('1')

unit = (lstNumerador, lstDenominador)
return unit
# What I expect
unit = (['kg', 'm', 'm', 's'], ['m', 's', 's'])
print(canonical(unit))
#(['kg', 'm'], ['s'])
unit = (['kg', 'm', 'm', 's'], ['s', 'm', 'm', 'kg'])
print(canonical(unit))
#(['1'], ['1'])
unit = (['s', 'kg', 'm', '1'], ['1', '1'])
print(canonical(unit))
#(['kg', 'm', 's'], ['1'])
unit = (['1', 'm', 's', '1', '1'], ['m', 's'])
print(canonical(unit))
#(['1'], ['1'])
unit = (['kg', 'm', 'm'], ['kg', 'm', 'm'])
print(canonical(unit))
#(['1'], ['1'])
# What I received instead
(['kg', 'm'], ['s'])
(['m', 's'], ['m', 's'])
(['kg', 'm', 's'], ['1'])
(['1', '1', 's'], ['s'])
(['m'], ['m'])

主要问题是您在正在迭代的列表上调用remove。这很少是一个好主意,因为它会"拉扯地毯"。可以跳过的一些值。

其次,嵌套循环通常效率不高。使用字典可以更好地做到这一点。

这个代码挑战实际上是Counter字典的理想候选。除了构造函数创建一个带有每个元素计数的字典之外,它还允许对两个这样的Counter对象进行减法,并使用一元操作符对Counter对象进行求反。您可以使用elements方法轻松地再次获得单个(重复的)元素。这一切都是非常方便的,以一种有效的方式达到预期的结果。

如下所示:

from collections import Counter
def canonical(unit):
diff = Counter(unit[0])
diff.subtract(unit[1])  # May produce negative frequencies
del diff["1"]  # NB: Counter objects don't raise "key error"
return list(diff.elements()) or ["1"], list((-diff).elements()) or ["1"]

见下文。我创建了你的单位的深度副本,所以它是坚不可摧的迭代/删除,并纠正了一些地方错误的逻辑。这将给出您期望的输出。

import copy
def canonical(unit):
numerador = unit[0]
denominador = unit[1]
numerador.sort()
denominador.sort()

lstNumerador = copy.deepcopy(numerador)
lstDenominador = copy.deepcopy(denominador)

for i in numerador:
for j in denominador:
if (i in lstNumerador) and (i in lstDenominador):
lstNumerador.remove(i)
lstDenominador.remove(i)


while lstNumerador.count('1') > 1:
lstNumerador.remove('1')

while lstDenominador.count('1') > 1:
lstDenominador.remove('1')

if len(lstNumerador) == 0:
lstNumerador.append('1')

if len(lstDenominador) == 0:
lstDenominador.append('1')

unit = (lstNumerador, lstDenominador)
return unit
unit1 = (['kg', 'm', 'm', 's'], ['m', 's', 's'])
unit2 = (['kg', 'm', 'm', 's'], ['s', 'm', 'm', 'kg'])
unit3 = (['s', 'kg', 'm', '1'], ['1', '1'])
unit4 = (['1', 'm', 's', '1', '1'], ['m', 's'])
unit5 = (['kg', 'm', 'm'], ['kg', 'm', 'm'])
units = [unit1, unit2, unit3, unit4, unit5]
for entry in units:
print(canonical(entry))

输出:

(['kg', 'm'], ['s'])
(['1'], ['1'])
(['kg', 'm', 's'], ['1'])
(['1'], ['1'])
(['1'], ['1'])

注意:我没有给分母加1,而是留了个空

def canonical(unit):
numerador = sorted([i for i in unit[0] if i!='1'])
denominador = sorted([i for i in unit[1] if i!='1'])

numCount= {i : numerador.count(i)-denominador.count(i) for i in set(numerador +denominador)}

numerador=[]
denominador= []
for num,count in numCount.items():
if count>0:
numerador+=[num]*count
elif count<0:
denominador+= [num]*-count
if len(numerador) == 0:
numerador=['1']
if len(denominador) == 0:
denominador=['1']

return (numerador, denominador)

相关内容

  • 没有找到相关文章

最新更新