Related
im now starting in programing. I get one exercise to generate a combination of 10 numbers with a set of numbers, and make a sum and the sum of that numbers need to be less than 800 and higher than 700, and print the result and combination (Print All combinations).
For example if the set of numbers is 10,20,30,40,50,60,70,80,90,100 and i need to generate a set of 10 numbers using the numbers i set and the sum of that combination need to be less 560 and higher than 500.
10+20+30+40+50+60+70+80+90+100 = 550
10+20+30+40+50+40+100+80+90+90 = 550
..
I start a code in Python, but im little stuck, how i can sum the combinations.
import itertools
myList = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
for i in range(len(myList)):
for combinations in itertools.combinations(myList, i):
print(combinations)
sum(e for e in combinations if e >= 550)
You're very close, but you need to filter based on whether sum(e) is in the desired range, not whether e itself is.
>>> from itertools import combinations
>>> myList = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
>>> [e for i in range(len(myList)) for e in combinations(myList, i) if 500 < sum(e) < 560]
[(20, 40, 50, 60, 70, 80, 90, 100), (30, 40, 50, 60, 70, 80, 90, 100), (10, 20, 30, 50, 60, 70, 80, 90, 100), (10, 20, 40, 50, 60, 70, 80, 90, 100), (10, 30, 40, 50, 60, 70, 80, 90, 100), (20, 30, 40, 50, 60, 70, 80, 90, 100)]
combinations only exists inside your inner for loop - you can sum it right after you print it simply with sum(combinations). Your sum() statement is outside the loop, where combinations is no longer defined.
Something like:
import itertools
myList = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
for i in range(len(myList)):
for combinations in itertools.combinations(myList, i):
if 500 < sum(combinations) < 560:
print(combinations, sum(combinations))
I have two sets of data here:
data_feb = ['1st February', 45, 68, 70, 61, 54, 80, 72, 69, 73, 72, 58, 72, 64, 45, 42]
data_aug = ['1st August', 19, 27, 41, 42, 9, 14, 29, 34, 25, 29, 44, 43, 6, 17]
I loop over it to create another list here:
for i in data_feb:
#
if type(i) == int:
feb_numbers.append(i)
for i in data_aug:
if type(i) == int:
aug_numbers.append(i)
But here i have an algorithm to sort them:
feb_zero_to_ten = []
feb_ten_to_twenty = []
feb_twenty_to_thirty = []
feb_thirty_to_forty = []
feb_forty_to_fifty = []
feb_fifty_to_sixty = []
feb_sixty_to_seventy = []
feb_seventy_to_eighty = []
feb_eighty_to_ninety = []
feb_ninety_to_hundred = []
aug_zero_to_ten = []
aug_ten_to_twenty = []
aug_twenty_to_thirty = []
aug_thirty_to_forty = []
aug_forty_to_fifty = []
aug_fifty_to_sixty = []
aug_sixty_to_seventy = []
aug_seventy_to_eighty = []
aug_eighty_to_ninety = []
aug_ninety_to_hundred = []
# for loop to iterate over months numbers, sorting them into their correct columns by the 'tens' digit
for i, j in zip(feb_numbers, aug_numbers):
if 0 <= i < 10 and 0 <= j < 10:
feb_zero_to_ten.append(i)
aug_zero_to_ten.append(j)
elif 10 <= i < 20 and 10 <= j < 20:
feb_ten_to_twenty.append(i)
aug_ten_to_twenty.append(j)
elif 20 <= i < 30 and 20 <= j < 30:
feb_twenty_to_thirty.append(i)
aug_twenty_to_thirty.append(j)
elif 30 <= i < 40 and 30 <= j < 40:
feb_thirty_to_forty.append(i)
aug_thirty_to_forty.append(j)
elif 40 <= i < 50 and 40 <= j < 50:
feb_forty_to_fifty.append(i)
aug_forty_to_fifty.append(j)
elif 50 <= i < 60 and 50 <= j < 60:
feb_fifty_to_sixty.append(i)
aug_fifty_to_sixty.append(j)
elif 60 <= i < 70 and 60 <= j < 70:
feb_sixty_to_seventy.append(i)
aug_sixty_to_seventy.append(j)
elif 70 <= i < 80 and 70 <= j < 80:
feb_seventy_to_eighty.append(i)
aug_seventy_to_eighty.append(j)
elif 80 <= i < 90 and 80 <= j < 90:
feb_eighty_to_ninety.append(i)
aug_eighty_to_ninety.append(j)
elif 90 <= i < 100 and 90 <= j < 100:
feb_ninety_to_hundred.append(i)
aug_ninety_to_hundred.append(j)
This approach using zip() is not working. I am wondering if using this approach is not worth it, also I am trying to make this code as efficient as possible so any pointers would be very helpful. Thank you.
data_feb = ['1st February', 45, 68, 70, 61, 54, 80, 72, 69, 73, 72, 58, 72, 64, 45, 42]
data_aug = ['1st August', 19, 27, 41, 42, 9, 14, 29, 34, 25, 29, 44, 43, 6, 17]
feb_numbers=[i for i in data_feb if isinstance(i,int) ]
aug_numbers=[i for i in data_aug if isinstance(i,int) ]
from itertools import groupby
[list(g) for k,g in groupby(sorted(aug_numbers),key=lambda x :x//10)]
Output:
[[6, 9], [14, 17, 19], [25, 27, 29, 29], [34], [41, 42, 43, 44]]
You can use itertools groupby to group those numbers
Your approach is flawed here. you test that both i and j are BOTH in a range but if you look at your numbers you will see that might not happen, thing like (45, 19) do not fit in any of the ifs. If you look at the logic you are trying to achieve then you will notice that you actually want to separate you number by their leading digit (the tens), An easy approach is to make buckets and fill them like this:
feb_buckets = [[] for item in range(10)] # this makes a list of 10 buckets (lists)
aug_buckets = [[] for item in range(10)]
for feb, aug in zip(feb_numbers,aug_numbers):
feb_bucket[feb//10].append(feb) # // is integer division (which rounds down)
aug_bucket[aug//10].append(aug)
once you understand the logic you can then simplify the code even further by taking #ajay approach and using itertools.groupby
Don't create all list by hand, just create list of lists and then access them by index.
For numbers in range 0 to 10 use feb[0] to 10 to 20 feb[1] etc.
If you don't know if the lists will have the same length, use function find_in_range for each list.
You can use this code below for this:
data_feb = ['1st February', 45, 68, 70, 61, 54, 80, 72, 69, 73, 72, 58, 72, 64, 45, 42]
data_aug = ['1st August', 19, 27, 41, 42, 9, 14, 29, 34, 25, 29, 44, 43, 6, 17]
#Dont create all list by hand, just create list of lists and then acces them by index
feb = [[] for i in range(10)]
aug = [[] for i in range(10)]
def find_in_range(in_list, out_list):
for x in sorted(in_list[1:]): #exclude the first index, because it is a string
for i in range(10):
if i*10 < x < (i+1)*10:
out_list[i].append(x)
find_in_range(data_feb, feb)
find_in_range(data_aug, aug)
print("Feb: ", feb)
print("Aug", aug)
This is the output:
Feb: [[], [], [], [], [42, 45, 45], [54, 58], [61, 64, 68, 69], [72, 72, 72, 73], [], []]
Aug [[6, 9], [14, 17, 19], [25, 27, 29, 29], [34], [41, 42, 43, 44], [], [], [], [], []]
As you can see the first four arrays of feb list are empty because in the list data_feb were not any numbers between 0-40.
One good way to accomplish the sort is by having a sorted list of lists. The final output would be fed_sorted and aug_sorted. The i-th list would be in range of [i*10, (i+1)*10).
data_feb = ['1st February', 45, 68, 70, 61, 54, 80, 72, 69, 73, 72, 58, 72, 64, 45, 42]
data_aug = ['1st August', 19, 27, 41, 42, 9, 14, 29, 34, 25, 29, 44, 43, 6, 17]
feb_numbers = [x for x in data_feb if type(x) == int]
aug_numbers = [x for x in data_aug if type(x) == int]
GROUP_SIZE = 10 # 0-9, 10-19, 20-29....
feb_sorted = [[x for x in feb_numbers if x in range(i * 10, (i + 1) * 10)] for i in range(GROUP_SIZE)]
aug_sorted = [[x for x in aug_numbers if x in range(i * 10, (i + 1) * 10)] for i in range(GROUP_SIZE)]
print(feb_sorted)
print(aug_sorted)
The first part of your code can be made more effecient like so:
data_feb = ['1st February', 45, 68, 70, 61, 54, 80, 72, 69, 73, 72, 58, 72, 64, 45, 42]
data_aug = ['1st August', 19, 27, 41, 42, 9, 14, 29, 34, 25, 29, 44, 43, 6, 17]
data_feb = [x for x in data_feb if x == int]
data_aug = [x for x in data_aug if x == int]
For the second part it is unclear what you are trying to achieve. Can you try to give some more background? Why do you need this many lists? What do you mean by sorting them and why do you need them sorted in this way?
I want to create an array with the following structure when printed:
1: (10,20),
2: (20,30),
3: (30,40),
4: (40,50),
and so on...
Really new to python so anything helps! Using python 3.
you can simply do by python range function range(start, end, stepsize)
final_lst = []
for i in range(10, 200, 10):
final_lst.append([i, i+10])
print(final_lst)
output
[[10, 20], [20, 30], [30, 40], [40, 50], [50, 60], [60, 70], [70, 80], [80, 90], [90, 100], [100, 110], [110, 120], [120, 130], [130, 140], [140, 150], [150, 160], [160, 170], [170, 180], [180, 190], [190, 200]]
::edit::
for i in range(1, 10):
print('%s: (%s,%s),'%(i, i*10, (i+1)*10))
output
1: (10,20),
2: (20,30),
3: (30,40),
4: (40,50),
5: (50,60),
6: (60,70),
7: (70,80),
8: (80,90),
9: (90,100),
take two variables cnt1 and cnt2
import numpy as np
myList = []
cnt1=1
cnt2=2
for i in range(n): #n is desired length
myList.append([10*cnt1,10*cnt2])
cnt1+=1
cnt2+=1
myArray = np.array(myList)
You can write a function that uses range to get a range of values and a list comprehension (basically an inline for-loop) to generate a list of tuples. Something like this:
def get_repeated_list(max_n):
values = range(10, max_n, 10)
return [(i, i+10) for i in values]
Example usage:
>>> get_repeated_list(50)
[(10, 20), (20, 30), (30, 40), (40, 50)]
Looks like what you want to do is is transform a list into another list of previous/next elements.
listA = [ 10 * i for i in range( N ) ]
listB = [ (listA[ i ], listA[ i + 1 ]) for i in range( len( listA ) - 1 ) ];
Let l be your list. It doesn't matter what is in it. Use zip to make a new list, with wanted feature. zip, matches elements of two list together. if you zip a list with itself, you'll have a new list that each element in first list is repeated twice in it.
l = [1, 2, 5, 11, 12]
for element in zip(l, l):
print(element)
output:
(1, 1)
(2, 2)
(5, 5)
(11, 11)
(12, 12)
I have a list that needs to be split into 4 separate lists with maximum size of 21 depending on the amount of items in the original list.
The master list can have from 1 to 84 items.
I want the items to start in a and fill up to a maximum of 21 in a, b, c, d
I have the following code that can split the items up no problem but I want to know if there is a shorter way to do this. I am repeating code a lot except the range.
codes = [x for x in range(80)] # range anywhere between 1-84
print(len(codes))
a = []
b = []
c = []
d = []
for i in range(0, 21):
try:
a.append(codes[i])
except IndexError:
pass
for i in range(21, 42):
try:
b.append(codes[i])
except IndexError:
pass
for i in range(42, 63):
try:
c.append(codes[i])
except IndexError:
pass
for i in range(63, 84):
try:
d.append(codes[i])
except IndexError:
pass
print(len(a), len(b), len(c), len(d))
print(a)
print(b)
print(c)
print(d)
Before that I had this code that works great for the whole 84 items as the order is not important..
a = []
b = []
c = []
d = []
for a1, b1, c1, d1 in zip(*[iter(codes)]*4):
a.append(a1)
b.append(b1)
c.append(c1)
d.append(d1)
However if i have say 4 items, it will add 1 to each
a = [0]
b = [1]
c = [2]
d = [3]
What I would like to obtain is
a = [0, 1, 2, 3]
b = []
c = []
d = []
You can simply use sublist
a = codes[0: 21]
b = codes[21:42]
c = codes[42:63]
d = codes[63:84]
This will be fine for your requirement
#SajalPreetSinghs answer is correct for a simple use case like OP's but it also has some disadvantages when it comes to scalability.
For example:
When you need 20 sublists instead of the actual 4. You would have to add 16 more lines and specify 2 different numbers per line each!
Now imagine you already extended the code to 20 sublists but now you want the maximum item count per sublist to be 37 instead of 21 - you would have to change 2*20 = 40 numbers!
Improved scalability with generators
So if you want something with a better scalability you could use the following code which makes usage of generators:
Code
def sublist(orig_list, list_of_subs, max_items_per_list):
def sublist_generator():
for sublist in list_of_subs:
yield sublist
sublist = sublist_generator()
current_sublist = next(sublist)
for element in orig_list:
current_sublist.append(element)
if len(current_sublist) == max_items_per_list: # current list is full
current_sublist = next(sublist) # so let current point to the next list
Setup and usage
import random
start = 1
stop = random.randint(2, 85) # generate random int inclusively 2 and 85
codes = [x for x in range(start, stop)] # stop is exclusive: range(1, 85) == [1, 2, ..., 84]
a, b, c, d = [], [], [], []
sublists = [a, b, c, d] # *1
sublist(codes, sublists, 21)
for sublist in sublists:
print(sublist)
Better scalability because
If you want to change the number of items per sublist you only have to pass in the new maximum number.
If you want to increase the number of sublists you only have to add more of them to the sublists variable which you pass to the function (see *1).
If you need this code more often it's no problem because you can comfortably call the function.
I hope this helps someone!
Cheers
winklerrr
You could use the zip_longest function from itertools
from itertools import zip_longest
master_list = range(0, 84)
iterables = [iter(master_list)] * 21
slices = zip_longest(*iterables, fillvalue=None)
for slice in slices:
print("slice", slice)
# slice (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)
# slice (21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41)
# slice (42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62)
# slice (63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83)
You can do it with using a list comprehension:
MAX_SIZE = 21
l = list(range(80))
l1,l2,l3,l4 = [l[i*MAX_SIZE: (i+1)*MAX_SIZE] for i in range(4)]
#l1=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,20],
# ....
#l4=[63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79]
What I would do would be just put it in one loop.
if index is 0 to 83
for i in range(0,84):
if i>=0 and i<=20:
a.append(codes[i])
elif i>20 and i<=41:
b.append(codes[i])
elif i>41 and i<=62:
c.append(codes[i])
elif i>62 and i<=83:
d.append(codes[i])
A solution using a list comprehension:
i_list = range(0,84)
r = 21
res = [i_list[i:i+r] for i in range(0,len(i_list),r)]
I have a list:
d = [23, 67, 110, 25, 69, 24, 102, 109]
how can I group nearest values with a dynamic gap, and create a tuple like this, what is the fastest method? :
[(23, 24, 25), (67, 69), (102, 109, 110)]
Like
d = [23,67,110,25,69,24,102,109]
d.sort()
diff = [y - x for x, y in zip(*[iter(d)] * 2)]
avg = sum(diff) / len(diff)
m = [[d[0]]]
for x in d[1:]:
if x - m[-1][0] < avg:
m[-1].append(x)
else:
m.append([x])
print m
## [[23, 24, 25], [67, 69], [102, 109, 110]]
Fist we calculate an average difference between sequential elements and then group together elements whose difference is less than average.