我执行了这段代码,该代码在上述列表中找到两个整数(在本例中为[2,4,5,1,6,40,-1]),该整数乘以20。一开始我有些卡住,但是在其中添加了一个功能可以解决我的问题。我向一位程序员的朋友展示了这段代码,他说我可以使这段代码更“ 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))
答案 0 :(得分:8)
我不一定认为这是“ unpythonic”,您正在使用标准的Python习惯用法来遍历数据并产生单个结果或obj2Arr = obj2Arr.stream()
.map(Car::getCarId)
.filter(carIdToId::containsKey)
.map(carId -> new Car(carIdToId.get(carId), carId))
.collect(Collectors.toList());
System.out.println(obj2Arr);
// [Car(id=2, carId=1234)]
。术语 Pythonic 含糊不清,是一个带有"I know it when I see it"参数的主题。
不是您产生了正确的实现。尽管None
遍历i
,但是given_numbers
遍历从j
到i + 2
的整数,将len(given_numbers)
中的值与索引混合?对于样本输入,您从半开范围[4,7),[6,7),[7,7)(空),[3,7),[8,7]中选取given_list
)(空),[42、7)(空)和[1,7)。完全能够给出正确答案的 是幸运的,而不是由于正确性;如果将列表j
赋予函数,将找不到解决方案!您想再次遍历[2, 10]
,受切片限制,或生成从given_numbers
的当前索引开始的索引,但是随后您的外部循环需要添加{{1 }}也致电:
i
或
enumerate()
所有这些都不是尽可能有效的。 Python标准库为您提供了生成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]
# ...
循环或切片或其他形式的过滤。
您的双循环应生成combinations的整数输入,因此请使用itertools.combinations()
object生成唯一的i, j
对:
for
这是假设可以有零个或多个这样的解决方案,而不仅仅是一个解决方案。
如果您只需要第一个结果或i, j
,则可以使用next()
function:
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]
接下来,您可能想反转问题,而不是产生所有可能的组合。如果将None
变成一个集合,则可以简单地检查目标数字20是否可以干净地除以给定的任何数字而没有余数,并且除法的结果更大和也是数字集中的整数。这样可以在线性时间内为您提供答案。
您可以通过除以小于目标值平方根的数字来进一步限制搜索,因为您找不到与输入数字相匹配的较大值(给定数字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
,根据定义n
将大于s
)。
如果我们在函数中添加目标数字的参数并将其设为generator function,则您将得到:
s * (s + 1)
此方法比测试所有排列要快很多,尤其是在需要查找所有可能因素的情况下。请注意,我在这里做了两个函数生成器,以使比较均匀:
n
请注意,我会生成10个不同的随机目标,以尽量避免在每种情况下都遇到幸运的最佳情况。
答案 1 :(得分:1)
[(i,j) for i in num_list for j in num_list if i<j and i*j==20]
答案 2 :(得分:0)
我可以考虑使用列表理解。如果给定列表中存在多个这样的对,这也有助于查找它们。
num_list = [2,4,5,1,6,40,-1]
mult_num = [(num_list[i],num_list[j]) for i in range(len(num_list)) for j in range(i+1, len(num_list)) if num_list[i]*num_list[j] == 20]
print mult_num
输出:
[(4, 5)]
答案 3 :(得分:0)
这是我的看法,它使用enumerate
:
def get_mult_num(given_list):
return [
item1, item2
for i, item1 in enumerate(given_list)
for item2 in given_list[:i]
if item1*item2 == 20
]
我认为您的朋友可能在暗示comprehensions可以使代码更简洁时使用(有时却不能)。
答案 4 :(得分:0)
您可以使用itertools.combinations(而不是嵌套循环)来查找所有数字对,从而使其更具Python风格。并非总是如此,但通常像在for i in range(len(L)):
中那样遍历索引比在for v in L:
中那样直接遍历索引要好得多。
Python还允许您通过yield
关键字将函数变成一个生成器,这样,您不仅可以返回乘以20的第一对,还可以通过遍历函数调用来获得每一对。 / p>
import itertools
def factors(x, numbers):
""" Generate all pairs in list of numbers that multiply to x.
"""
for a, b in itertools.combinations(numbers, 2):
if a * b == x:
yield (a, b)
numbers = [2, 4, 5, 1, 6, 40, -1]
for pair in factors(20, numbers):
print(pair)
答案 5 :(得分:0)
我想到了这个。它稍微颠倒了方法,因为它在num_list
中搜索所需的配对伙伴,而迭代值val
将会乘以20。这样可以简化代码,并且即使不是最有效的方式也不需要导入。
for val in num_list:
if 20 / val in num_list:
print(val, int(20/val))