Найти два числа из списка, которые складываются в определенный номер - PullRequest
0 голосов
/ 27 августа 2018

Это очень плохо и грязно, я новичок в этом, пожалуйста, помогите мне.

По сути, я пытался найти два числа из списка, которые складываются в целевое число.

Я настроил пример с lst = [2, 4, 6, 10] и целевым значением target = 8. Ответ в этом примере будет (2, 6) и (6, 2).

Ниже приведен мой код, но он длинный и безобразный, и я уверен, что есть лучший способ сделать это. Можете ли вы посмотреть, как я могу улучшить мой код ниже?

from itertools import product, permutations

numbers = [2, 4, 6, 10]
target_number = 8

two_nums = (list(permutations(numbers, 2)))
print(two_nums)

result1 = (two_nums[0][0] + two_nums[0][1])
result2 = (two_nums[1][0] + two_nums[1][1])
result3 = (two_nums[2][0] + two_nums[2][1])
result4 = (two_nums[3][0] + two_nums[3][1])
result5 = (two_nums[4][0] + two_nums[4][1])
result6 = (two_nums[5][0] + two_nums[5][1])
result7 = (two_nums[6][0] + two_nums[6][1])
result8 = (two_nums[7][0] + two_nums[7][1])
result9 = (two_nums[8][0] + two_nums[8][1])
result10 = (two_nums[9][0] + two_nums[9][1])

my_list = (result1, result2, result3, result4, result5, result6, result7, result8, result9, result10)
print (my_list)

for i in my_list:
  if i == 8:
print ("Here it is:" + str(i))

Ответы [ 5 ]

0 голосов
/ 19 ноября 2018

Если вы пытаетесь найти ответ для нескольких целых чисел с длинным списком, который имеет повторяющиеся значения, я бы рекомендовал использовать frozenset. «Проверенный» ответ получит только первый ответ, а затем остановится.

import numpy as np
numbers = np.random.randint(0, 100, 1000)
target = 17

def adds_to_target(base_list, target):
    return_list = []
    for i in range(len(base_list)):
        return_list.extend([list((base_list[i], b)) for b in base_list if (base_list[i] + b)==target])
    return set(map(frozenset, return_list))

# sample output
{frozenset({7, 10}),
 frozenset({4, 13}),
 frozenset({8, 9}),
 frozenset({5, 12}),
 frozenset({2, 15}),
 frozenset({3, 14}),
 frozenset({0, 17}),
 frozenset({1, 16}),
 frozenset({6, 11})}

1) В первом цикле for списки, содержащие два целых числа, которые суммируются с целевым значением, добавляются в «return_list», т.е. создается список списков.

2) Затем Frozenset вынимает все дубликаты пар.

%timeit adds_to_target(numbers, target_number)
# 312 ms ± 8.86 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
0 голосов
/ 27 августа 2018

Понимание списка здесь будет хорошо работать. Попробуйте это:

from itertools import permutations

numbers = [2, 4, 6, 10]
target_number = 8

solutions = [pair for pair in permutations(numbers, 2) if sum(pair) == 8]
print('Solutions:', solutions)

По сути, это понимание списка рассматривает все пары, которые возвращает permutations(numbers, 2), но сохраняет только те, чья общая сумма равна 8.

0 голосов
/ 27 августа 2018

Вы можете сделать это в одну строку с пониманием списка, как показано ниже:

from itertools import permutations

numbers = [2, 4, 6, 10]
target_number = 8
two_nums = (list(permutations(numbers, 2)))

result=[i for i in two_nums if i[0]+i[1] == target_number]

[(2,6), (6,2)]

0 голосов
/ 27 августа 2018

Самый простой общий способ сделать это состоит в том, чтобы выполнить итерацию по вашему списку и для каждого элемента выполнить итерацию по остальной части списка, чтобы увидеть, соответствует ли он целевому значению. Недостатком этого является операция O (n ^ 2). Я не знаю, изо всех сил, есть ли более эффективное решение. Я не уверен на 100%, что мой синтаксис правильный, но он должен выглядеть примерно так:

done = False
for i, val in enumerate(numbers):
    if val >= target_number:
        continue
    for j, val2 in enumerate(numbers, i+1):
        if val + val2 == target_number:
            print ("Here it is: " + str(i) + "," + str(j))
            done = True
            break
    if done:
        break

Конечно, вы должны создать это как функцию, которая возвращает ваш результат, а не просто печатать его. Это устранит необходимость в переменной "done".

0 голосов
/ 27 августа 2018

Для каждого номера в списке вы можете найти его дополнительный (номер, который при добавлении к предыдущему даст требуемую target сумму). Если она существует, найдите пару и выйдите, в противном случае продолжайте.

Это будет выглядеть следующим образом:

numbers = [2, 4, 6, 10]
target_number = 8

for i, number in enumerate(numbers[:-1]):  # note 1
    complementary = target_number - number
    if complementary in numbers[i+1:]:  # note 2
        print("Solution Found: {} and {}".format(number, complementary))
        break
else:  # note 3
    print("No solutions exist")

, который производит:

Solution Found: 2 and 6

Примечания:

  1. Вам не нужно проверять последний номер; если бы была пара, вы бы ее уже нашли.
  2. Обратите внимание, что проверка членства (что довольно дорого в списках) оптимизирована, поскольку она рассматривает только срез numbers[i+1:]. Предыдущие номера уже проверены. Положительным побочным эффектом среза является то, что наличие одного 4 в списке не дает пары для целевого значения 8.
  3. Это отличная установка для объяснения неправильно понятого и часто сбивающего с толку использования else в for -петлях. else срабатывает только в том случае, если цикл не был внезапно завершен break.


Если решение 4 - 4 приемлемо для вас, даже если в списке есть single 4, вы можете изменить его следующим образом:

numbers = [2, 4, 6, 10]
target_number = 8

for i, number in enumerate(numbers):
    complementary = target_number - number
    if complementary in numbers[i:]:
        print("Solution Found: {} and {}".format(number, complementary))
        break
else:
    print("No solutions exist")
...