找到两个乘以20的整数。我可以使此代码更“ pythonic”吗?

时间:2019-02-06 14:50:52

标签: python python-3.x

我执行了这段代码,该代码在上述列表中找到两个整数(在本例中为[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)) 

6 个答案:

答案 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遍历从ji + 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))