def somalist (lista):
listasoma = [0,0,0,0,0,0,0,0,0,0,0]
for i in lista:
for g in i:
if i.index(g) != 0 and i.index(g) != 1 and i.index(g) != 2 and i.index(g) != 3:
listasoma[i.index(g)] += g
else:
listasoma[i.index(g)] = g
print(listasoma)
return(listasoma)
x = [[1,2,3,4,5,6,7,8,9,10,11],[1,2,3,4,5,6,7,8,9,10,11],[1,2,3,4,5,6,7,8,9,10,11]]
print(somalist(x))
is that the function, it works doing the sum of each sublist but it preserves the the index [0], [1], [2] and [3] and sum the anothers. In this example I will use the list x, in this list the function works correctly. The exit of the program is:
[1, 2, 3, 4, 32, 18, 21, 24, 27, 30, 22]
is what I've said it preserves the members [0],[1],[2],[3] and sum the other indices of each sublist.
But when we use some number more than once, it fails.
using:X = [[1,2,3,4,5,6,7,8,9,10,11],[1,2,3,4,**6**,6,7,8,9,10,11],[1,2,3,4,5,6,7,8,9,10,11]]
the 6 (index 4) in second sublist was writen twice (the another at the index 5 at the same sublist)
the exit was :[1, 2, 3, 4, **22**, 12, 21, 24, 27, 30, 33]
It's wrong!
The correct exit should be: [ 1, 2, 3, 4, 16, 18, 21, 24, 27, 30, 33]
Can someone tell me where my code is wrong?
I would recommend ditching the index() approach entirely.
def somalist (lista):
return lista[0][:4] + [sum(item) for item in list(zip(*lista))[4:]]
This works on lists with repeated elements.
v
>>> x = [[1,2,3,4,5,6,7,8,9,10,11],[1,2,3,4,5,6,7,8,9,10,11],[1,2,3,4,5,6,7,8,9,10,11]]
>>> X = [[1,2,3,4,5,6,7,8,9,10,11],[1,2,3,4,6,6,7,8,9,10,11],[1,2,3,4,5,6,7,8,9,10,11]]
>>> print(somalist(x))
[1, 2, 3, 4, 15, 18, 21, 24, 27, 30, 33]
>>> print(somalist(X))
[1, 2, 3, 4, 16, 18, 21, 24, 27, 30, 33]
^^
Related
Have this so far, and essentially want to get there is something wrong with the position of last_odd as the compiler says the pop index is out of range?
def remove_last_odd(numbers):
has_odd = False
last_odd = 0
for num in range(len(numbers)):
if numbers[num] % 2 == 1:
has_odd = True
last_odd = numbers[num]
if has_odd:
numbers.pop(last_odd)
numbers = [1, 7, 2, 34, 8, 7, 2, 5, 14, 22, 93, 48, 76, 15, 6]
Remove the item at the given position in the list, and return it. If no index is specified, a.pop() removes and returns the last item in the list.
So basically, the solution to your problem would be to replace last_odd = numbers[num] with last_odd = num.
As #DeepSpace said, list.pop will
Remove the item at the given position in the list, and return it. If no index is specified, a.pop() removes and returns the last item in the list.
So basically, the solution to your problem would be to replace last_odd = numbers[num] with last_odd = num.
list.pop() receive index as argument and remove the value. So, last_odd should be assigned to num instead of numbers[num]
Your function doesn't have return value yet. It should return numbers list.
def remove_last_odd(numbers):
for num in range(len(numbers)):
if numbers[num] % 2 == 1:
last_odd = num
numbers.pop(last_odd)
return numbers
numbers = [1, 7, 2, 34, 8, 7, 2, 5, 14, 22, 93, 48, 76, 15, 6]
print(remove_last_odd(numbers))
# [1, 7, 2, 34, 8, 7, 2, 5, 14, 22, 93, 48, 76, 6]
Or iterating numbers value and using remove() method instead of pop():
def remove_last_odd(numbers):
for num in numbers:
if num % 2: last_odd = num
numbers.remove(last_odd)
return numbers
numbers = [1, 7, 2, 34, 8, 7, 2, 5, 14, 22, 93, 48, 76, 15, 6]
print(remove_last_odd(numbers))
# [1, 7, 2, 34, 8, 7, 2, 5, 14, 22, 93, 48, 76, 6]
No need to reverse the list but you can search it in reverse.
def remove_last_odd(numbers):
for i in range(len(numbers)-1, -1, -1):
if numbers[i] & 1:
numbers.pop(i)
break
numbers = [1, 7, 2, 34, 8, 7, 2, 5, 14, 22, 93, 48, 76, 15, 6]
remove_last_odd(numbers)
print(numbers)
Output:
[1, 7, 2, 34, 8, 7, 2, 5, 14, 22, 93, 48, 76, 6]
Option:
If you insist on a 'forward' search then:
def remove_last_odd(numbers):
ri = -1
for i, v in enumerate(numbers):
if v & 1:
ri = i
if ri >= 0:
numbers.pop(ri)
To get the index of the last odd element you can use the reversed() iterator which will not reverse the original list object.
A quick way to get the index is:
>>> numbers = [1, 7, 2, 34, 8, 7, 2, 5, 14, 22, 93, 48, 76, 15, 6]
>>> -next(filter(lambda v: v[1]%2==1, enumerate(reversed(numbers))))[0]
-1
Even for very large lists with a lot of even numbers at the end the result will be delivered quite quick (compared with the proposed code):
>>> from timeit import timeit
>>> def find_last_odd(numbers):
for num in range(len(numbers)):
if numbers[num] % 2 == 1:
last_odd = num
return last_odd
>>> numbers2=numbers+([2]*10000) # create a list with 10000 even numbers at the end!
>>> timeit(lambda: find_last_odd(numbers2),number=100)
0.5675344999999936
>>> timeit.timeit(lambda: -next(filter(lambda v: v[1]%2==1, enumerate(reversed(numbers2)))).__getitem__(0),number=100)
0.10892959999998197
I have a list for example:
[1,2,3,4]
I want to have ten repeats of the list, and every element increase by 1 than the previous element like:
[1,2,3,4,2,3,4,5,3,4,5,6................40 elements]
Thanks for the previous answers!
The closest answer I got so far:
list = [1,2,3,4]
n = 4 #number of elements in the list
newList = [ ]
for i in range(10):
for element in list:
newList.append(element + i*n)
print(newList)
print(len(newList))
The output:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40]
40
temp = [1, 2, 3, 4]
lst = [i + j for i in range(9) for j in temp]
print(lst)
# which equals to this:
temp = [1, 2, 3, 4]
lst2 = []
for i in range(9):
for j in temp:
lst2.append(i + j)
print(lst2)
plz have a look. I don't think it goes upto [1,2,..40] , only goes upto[1,2,.. 14].
At each iteration you are increasing the value by 1 so, after 10 times repeating every no in the array will be increased by 10. So 4 will be 14 which will be the last element not 40.
Here's my code according to your requirement,
arr = [1,2,3,4]
answer = [ ]
for i in range(11):
for element in arr:
answer.append(element + i)
print(answer)
I have a list of elements and want to get the sum of this list:
a = [4, 5, "X", "X"].
But X can be 2 different values, 2 or 3. So there are 4 sums of this list:
sum1 = sum([4, 5, 2, 2]) = 13
sum2 = sum([4, 5, 2, 3]) = 14
sum3 = sum([4, 5, 3, 2]) = 14
sum4 = sum([4, 5, 3, 3]) = 15
Basically I want to get a tuple (or list) of all possible sums of the list, like:
sums = (13, 14, 14, 15)
For an input list with 0 X, I want to get a tuple with 1 element, for a tuple with 1 X a tuple of 2 elements, with 2 X tuple with 4 elements...with n X a tuple of 2^n elements.
Similar to Michael's answer, also using itertools.product, but with a dictionary mapping elements to possible values. This might be more flexible, allowing placeholders in all positions and different values for different placeholders, and also makes the code a bit simpler IMHO.
>>> from itertools import product
>>> a = [4, 5, "X", "X"]
>>> vals = {"X": [2, 3]}
>>> [sum(p) for p in product(*[vals.get(x, [x]) for x in a])]
[13, 14, 14, 15]
You can use itertools.product and a list comprehension
from itertools import product
a = [4, 5, "X", "X"]
r = a.count('X')
[sum(a[:len(a)-r] + [*i]) for i in product([2,3], repeat=r)]
Output
[13, 14, 14, 15]
Testing with more cases
#test cases
for n in range(5):
a=[4,5, *['X']*n] # [4,5] .... [4,5,'X','X','X','X']
r = a.count('X')
print([sum(a[:len(a)-r] + [*i]) for i in product([2,3], repeat=r)])
Output
[9]
[11, 12]
[13, 14, 14, 15]
[15, 16, 16, 17, 16, 17, 17, 18]
[17, 18, 18, 19, 18, 19, 19, 20, 18, 19, 19, 20, 19, 20, 20, 21]
Consider two lists of identical length:
t is a list of irregular-intervals of times in seconds, arranged chronologically
pt is a list of sequences of numbers 1,2,3 wsuch that a 1 is followed by a consecutive string of 2's, then followed by a 3.
1 = start of event, 2 = continuation of event, 3 = end of event
This means that for a single event, the sequence begins with a single 1, is followed by a consecutive string of 2s (how many times it repeats will vary), and finally ends in a single 3.
There is more than 1 event contained in this vector
For example, the input could look like:
# |--Event #1-| |---Event #2----| |Event #3 |
pt = [1, 2, 2, 3, 1, 2, 2, 2, 3, 1, 2, 3 ]
t = [1, 10, 13, 14, 17, 20, 21, 25, 37, 32, 33, 38]
Is there a 1-liner that doesn't involve multiple nested loops that we could use that would calculate the difference in time values in t for each event sequence in pt?
For example, the desired output for the above inputs would be a list of length 3 (because there are 3 events) where the output is
Output: [13, 20, 6]
### Explanation:
# 13 = 14-1 = t[position where pt shows first 3] - t[position where pt shows first 1]
# 20 = 37-17 = t[position where pt shows second 3] - t[position where pt shows second 1]
# 6 = 38-32 = t[position where pt shows third 3] - t[position where pt shows third 1]
using pure python:
pt = [1, 2, 2, 3, 1, 2, 2, 2, 3, 1, 2, 3 ]
t = [1, 10, 13, 14, 17, 20, 21, 25, 37, 32, 33, 38]
l = [y for x, y in zip(pt,t) if x in [1,3]]
print([l[i:i+2][1] - l[i:i+2][0] for i in range(0, len(l), 2)])
[13, 20, 6]
using more_itertools.chunked():
from more_itertools import chunked
print([y-x for x,y in chunked([y for x, y in zip(pt,t) if x in [1,3]], 2)])
[13, 20, 6]
explanation
If you look close, we see this list comprehension occurring multiple times. This is the center of the solution!
[y for x, y in zip(pt,t) if x in [1,3]]
So, what's going on?
Using the zip function, we make a list of the paired elements, and if the x element (1st list element pair) is either 1 or 3 we add it to the list.
This gives us a list of the differences we need to find.
#|---| |----| |----|
[1, 14, 17, 37, 32, 38]
Now comes the second part, getting the differences from these. We essentially need to make pairs from this, the method I'm going to use here is chunking. The pure python way to partition a list into chunks is as follows:
#given a list l
chunklen = 2
[l[i:i+chunklen] for i in range(0, len(l), chunklen)]
using this we could partition the [1, 14, 17, 37, 32, 38] list to:
[[1, 14], [17, 37], [32, 38]]
but it's far simpler to just get the differences immediately!
l[i:i+chunklen][1]-l[i:i+chunklen][0]
#given l[i:i+chunklen] as [1, 14] this would return 14-1 i.e. 13
This seems to work
pt = [1, 2, 2, 3, 1, 2, 2, 2, 3, 1, 2, 3 ]
t = [1, 10, 13, 14, 17, 20, 21, 25, 37, 32, 33, 38]
st = 0
lst = []
for x in zip(pt,t):
if x[0] == 1: st = x[1]
if x[0] == 3:
d = x[1] - st
lst.append(d)
print(lst)
Output
[13, 20, 6]
Code:
pt = [1, 2, 2, 3, 1, 2, 2, 2, 3, 1, 2, 3 ]
t = [1, 10, 13, 14, 17, 20, 21, 25, 37, 32, 33, 38]
events_t =[]
arr = []
for pt_ele, t_ele in zip(pt, t):
arr.append(t_ele)
if pt_ele == 3:
events_t.append(arr)
arr = []
print(events_t)
res = [i[-1] - i[0] for i in events_t]
print(res)
Output:
[[1, 10, 13, 14], [17, 20, 21, 25, 37], [32, 33, 38]]
[13, 20, 6]
input:
a sorted list, like this:[1,2,3,8,10,15,16,17,18,22,23,27,30,31]
a threshold, like this: max_diff = 2
expected output:
a list of sub lists; each sub list contains the values that the neighboring difference is smaller than max_diff, like this: [[1, 2, 3], [8, 10], [15, 16, 17, 18], [22, 23], [27], [30, 31]]
Here's how I did this, I am wondering if there is a better way to do this.
test_list = [1,2,3,8,10,15,16,17,18,22,23,27,30,31]
max_diff = 2
splited_list = []
temp_list = [test_list[0]]
for i in xrange(1,len(test_list)):
if test_list[i] - temp_list[-1] > max_diff:
splited_list.append(temp_list)
temp_list = [test_list[i]]
else:
temp_list.append(test_list[i])
if i == len(test_list) -1:
splited_list.append(temp_list)
print splited_list
You can use enumerate and zip function within a list comprehension to find the indices of the elements that value difference is larger than 2, then split your list based on index list :
>>> li =[1, 2, 3, 8, 10, 15, 16, 17, 18, 22, 23, 27, 30, 31]
>>> inds=[0]+[ind for ind,(i,j) in enumerate(zip(li,li[1:]),1) if j-i>2]+[len(li)+1]
>>> [li[i:j] for i,j in zip(inds,inds[1:])]
[[1, 2, 3], [8, 10], [15, 16, 17, 18], [22, 23], [27], [30, 31]]
>>> a = [1,2,3,8,10,15,16,17,18,22,23,27,30,31]
>>> b = a[1:] #offset by 1 position
>>> b
[2, 3, 8, 10, 15, 16, 17, 18, 22, 23, 27, 30, 31]
>>> c = [(i[1] - i[0]) for i in zip(a[:-1], b)]
>>> c #position diff
[1, 1, 5, 2, 5, 1, 1, 1, 4, 1, 4, 3, 1]
>>> d = [i[0] for i in enumerate(c) if i[1] > 2]
>>> d #split position
[2, 4, 8, 10, 11]
>>> e = [-1]+d+[len(a)]
>>> e #add start end to split position
[-1, 2, 4, 8, 10, 11, 14]
>>> [a[l[0]+1: l[1]+1] for l in zip(e, e[1:])]
[[1, 2, 3], [8, 10], [15, 16, 17, 18], [22, 23], [27], [30, 31]]
#split result
Rearranging your lines leads to a more compact form:
test_list = [1,2,3,8,10,15,16,17,18,22,23,27,30,31]
max_diff = 2
splited_list = []
prev_element = float('-inf')
for element in test_list:
if element - prev_element > max_diff:
splited_list.append([])
splited_list[-1].append(element)
prev_element = element
print splited_list
Works on all iterables
def split_by_threshold(seq, max_diff=2):
it = iter(seq)
last = next(it)
part = [last]
for curr in it:
if curr - last > max_diff:
yield part
part = []
part.append(curr)
last = curr
yield part
l = [1,2,3,8,10,15,16,17,18,22,23,27,30,31]
print(list(split_by_threshold(l)))