简体   繁体   中英

Python one or more elements in a list whose sum or value is equal to a given condition

I am making an algorithm that can get an element or a list of elements from a list that is equal or whose sum is equal to a given number.

list1 = [1,1, 1, 1,2,3,3,4,7,8,9, 45, 67, 98] (Sum up to 3)

list2 = [5,40, 70, 120, 150]      (Sum up to 130)

From list1 want the elements that sum up 3, but my goal is to find if that exact number like say 3 is in the list, then select it else select other numbers that sum up to 3.

From list2 I need a value equal to 130 or elements that sum up to 130, as you see there are no values that match so I need to select an element thats closest match to it say 150 then save it to another array. NB: Plz not that there's no limit on elements to combine, as long as the elements total up to the required number but i would prefer to first look in the list to see if there's an exact number matching.

Below is the code I am using but I can only get the values that sum up, I need help to solve the more complex solutions.

class select_pair():
  def __init__(self, l, target):
  self.__l = l
  self.__target = target
  if not isinstance(l, list):
  raise TypeError("it must be a list")
  elif not isinstance(target, int):
  raise TypeError("it must be an integer")
  for i in range(len(l)-1):

  if l[i] == target:  
    print("from 1st index1:{}".format(i))
    break
  elif l[i]+l[i+1] == target:
   print("from second index1:{}, index2:{}".format(i+1, i+2))
   break


p = select_pair(list1,3)
p = select_pair(list2,130)

There's probably no better way then to test all the combinations of 1, 2, 3, ... elements of the list whether they match the given target sum. However, you can combine your three cases (perfect match, matching sum, and nearest sum) by using a tuple (difference to target, number of element) as the key to be minimized.

from itertools import combinations    
def combs(lst, n):
    return (c for k in range(1, n+1) for c in combinations(lst, k))

def best_match(lst, target, n=3):
    return min(combs(lst, n), key=lambda c: (abs(target - sum(c)), len(c)))

list1 = [1,1, 1, 1,2,3,3,4,7,8,9, 45, 67, 98]
list2 = [5,40, 70, 120, 150]
print(best_match(list1, 3))   # (3,)
print(best_match(list2, 130)) # (5, 120)

Here, n is the maximum number of elements to combine. You can of course also use a higher value than 3 , but for longer lists, this will mean that there are a lot more elements to compare. Also, note that this function will not stop early if a perfect match is found, although this could be achieved using a regular loop instead of min .

def best_match_stop_early(lst, target, n=3):
    best = None
    for c in combs(lst, n):
        v = (abs(target - sum(c)), len(c), c)
        if best is None or v < best:
            best = v
            if v[0] == 0:
                return v[2]
    return best[2]

Similarly, you can tweak the combs function to not just generate all the combinations, but to abort early, eg if the sum of a combination is already larger than the target sum, then adding more numbers to that combination will not make it better -- but still other longer combinations could be better. However, this will only work for this specific target function, and only if there are no negative numbers in the list.

As I've understood, your requirement is to either search and find a number from a list, or display the numbers needed from the list to sum up to get the input number. Correct me if I am wrong.

If that's the case, you can get the total sum, and count in this way using Python3:

list1 = [1,1, 1, 1,2,3,3,4,7,8,9, 45, 67, 98]
input_number = int(input("Enter the number: "))

count = 0
total = 0

if input_number in list1:
    print(f"{input_number} found !")
else:
    for i in list1:
        count+=1
        total+=i
        if total >= input_number:
            print(f"Total is {total}")
            print(f"First {count} numbers from the list were added. ")
            break

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM