gpt4 book ai didi

python - 找到两个乘以 20 的整数。我可以让这段代码更多 "pythonic"吗?

转载 作者:行者123 更新时间:2023-11-28 19:52:26 33 4
gpt4 key购买 nike

我编写的这段代码在上述列表(在本例中为 [2,4,5,1,6,40,-1])中找到两个乘以 20 的整数。一开始我有点卡住了,但是向它添加一个功能解决了我的问题。我向我的一位程序员 friend 展示了这段代码,他说我可以让这段代码更“pythonic”,但我不知道怎么做。

代码如下:

num_list = [2,4,5,1,6,40,-1]

def get_mult_num(given_list):
for i in given_list:
for j in range(i+1, len(given_list)): #for j not to be == i and to be in the list
mult_two_numbers = i * j
if mult_two_numbers == 20:
return i,j

print(get_mult_num(num_list))

最佳答案

我不一定认为它是“unpythonic”,您使用的是标准 Python 习惯用法来循环处理您的数据并生成单个结果或None。术语 Pythonic 是模糊的,一个在 "I know it when I see it" 中被破坏的主题参数。

并不是说您生成了正确 实现。 i 遍历 given_numbersj 遍历从 i + 2len( given_numbers),将 given_list 中的值与索引混合?对于您的样本输入,您从半开范围 [4, 7), [6, 7), [7, 7)(空),[3, 7), [ 8, 7)(空),[42, 7)(空)和 [1, 7)。它产生正确答案完全是运气,而不是因为正确;如果你给你的函数列表 [2, 10],它不会找到解决方案!您想要遍历 given_numbersagain,限制切片,或者生成从 i 的当前索引开始的索引,但是您的外循环需要也添加一个 enumerate() 调用:

for ii, i in enumerate(given_numbers):
for j in given_numbers[ii + 1:]:
# ...

for ii, i in enumerate(given_numbers):
for jj in range(ii + 1, len(given_numbers)):
j = given_numbers[jj]
# ...

所有这些都没有达到应有的效率; Python 标准库为您提供了生成 i, j 对的工具,无需嵌套的 for 循环或切片或其他形式的过滤。

你的双循环应该生成 combinations的整数输入,所以使用 itertools.combinations() object生成唯一的 i, j 对:

from itertools import combinations

def get_mult_num(given_list):
return [(i, j) for i, j in combinations(given_list, 2) if i * j == 20]

这假设可以有零个或多个这样的解决方案,而不仅仅是一个解决方案。

如果您只需要第一个结果或,您可以使用next() function :

def get_mult_num(given_list):
multiplies_to_20 = (
(i, j) for i, j in combinations(given_list, 2)
if i * j == 20)
return next(multiplies_to_20, None)

接下来,您可能想要反转问题,而不是产生所有可能的组合。如果将 given_list 变成一个集合,您可以简单地检查目标数字 20 是否可以被任何给定数字干净地除掉而没有余数,以及除法的结果在哪里更大 也是数字集中的一个整数。这会在线性时间内为您提供答案。

您可以通过除以小于目标值平方根的数字来进一步限制搜索,因为您不会在输入数字中找到更大的值来匹配(给定一个数字 n它是 s 的平方根,根据定义 s * (s + 1) 将大于 n

如果我们向函数添加目标数字的参数并将其设为 generator function ,然后你得到:

def gen_factors_for(target, numbers):
possible_j = set(numbers)
limit = abs(target) ** 0.5
for i in numbers:
if abs(i) < limit and target % i == 0:
j = target // i
if j in possible_j and abs(j) > abs(i):
yield i, j

这种方法比测试所有排列要快很多,尤其是当您需要找到所有可能的因素时。请注意,我在这里制作了两个函数生成器以平衡比较:

>>> import random, operator
>>> from timeit import Timer
>>> def gen_factors_for_division(target, numbers):
... possible_j = set(numbers)
... limit = abs(target) ** 0.5
... for i in numbers:
... if abs(i) < limit and target % i == 0:
... j = target // i
... if j in possible_j and abs(j) > abs(i):
... yield i, j
...
>>> def gen_factors_for_combinations(target, given_list):
... return ((i, j) for i, j in combinations(given_list, 2) if i * j == target)
...
>>> numbers = [random.randint(-10000, 10000) for _ in range(100)]
>>> targets = [operator.mul(*random.sample(set(numbers), 2)) for _ in range(5)]
>>> targets += [t + random.randint(1, 100) for t in targets] # add likely-to-be-unsolvable numbers
>>> for (label, t) in (('first match:', 'next({}, None)'), ('all matches:', 'list({})')):
... print(label)
... for f in (gen_factors_for_division, gen_factors_for_combinations):
... test = t.format('f(t, n)')
... timer = Timer(
... f"[{test} for t in ts]",
... 'from __main__ import targets as ts, numbers as n, f')
... count, total = timer.autorange()
... print(f"{f.__name__:>30}: {total / count * 1000:8.3f}ms")
...
first match:
gen_factors_for_division: 0.219ms
gen_factors_for_combinations: 4.664ms
all matches:
gen_factors_for_division: 0.259ms
gen_factors_for_combinations: 3.326ms

请注意,我生成了 10 个不同的随机目标,以尽量避免两种方法都碰上幸运的最佳情况。

关于python - 找到两个乘以 20 的整数。我可以让这段代码更多 "pythonic"吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54556363/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com