I have this question about loops.
Imagine You have this data array:
list = [1,2,3,4,5,6,7,8,9,8,7,6,5,4,3,2,1]
How would You write a loop which checks if the previous number is lower, and the next after the checked one (Condition looks like this [5,6,5]). So the loop will get to number 9 and print it or save it, whatever.
Using next with a generator expression:
lst = [1,2,3,4,5,6,7,8,9,8,7,6,5,4,3,2,1]
res = next(j for i, j, k in zip(lst, lst[1:], lst[2:]) if i < j and i == k)
If you need all such numbers, use a list comprehension instead:
res = [j for i, j, k in zip(lst, lst[1:], lst[2:]) if i < j and i == k]
If you need a condition that will show all numbers that are higher than their previous and next ones:
lst = [1,2,3,4,3,2,3,1,2,1,2,3,4,5,6,7,8,6]
res = [j for i, j, k in zip(lst, lst[1:], lst[2:]) if i < j > k]
[4, 3, 2, 8] is printed.
Explanation
You can iterate the list with shifted versions of itself via zip.
For each triplet, test your two conditions.
Use next to extract such triplets; if no such triplet exists, you will meet StopIteration error.
Never name a variable after a built-in, e.g. use lst instead of list.
You could just write a simple loop that checks the previous number is less than the current number, and the next number is equal to the previous number:
lst = [1,2,3,4,5,6,7,8,9,8,7,6,5,4,3,2,1]
for i in range(len(lst)):
if lst[i-1] < lst[i] and lst[i-1] == lst[i+1]:
print(lst[i])
# 9
Related
import random
def mainlist(list, size, min, max):
for i in range(size):
list.append(random.randint(min, max))
print(list)
def counterlist(list):
for i in list:
if i<0:
x=sum(list[(list.index(i)+1):])
print('Reqemlerin cemi:', x)
break
list = []
mainlist(list, 10, -10, 30)
counterlist(list)
I need to calculate sum of numbers after 1st negative number in this random list, did it in second function but want to know is there way not using the sum() function?
Explicitly using an iterator makes it nicer and more efficient:
def counterlist(lst):
it = iter(lst)
for i in it:
if i < 0:
print('Reqemlerin cemi:', sum(it))
No idea why you wouldn't want to use the sum function, that's absolutely the right and best way to do it.
Try this:
import random
lst = [random.randint(-10, 30) for _ in range(10)]
print(sum(lst[next(i for i, n in enumerate(lst) if n < 0) + 1:]))
First you generate the list lst. Then, you iterate over your list and you find the first negative element with next(i for i, n in enumerate(lst) if n < 0). Finally, you compute the sum of the portion of the list you're interested about.
If you really don't want to use sum but keep things concise (and you're using python >= 3.8):
import random
lst = [random.randint(-10, 30) for _ in range(10)]
s = 0
print([s := s + x for x in lst[next(i for i, n in enumerate(lst) if n < 0) + 1:]][-1])
Assuming there's a negative value in the list, and with a test list "a":
a = [1,2,3,-7,2,3,4,-1,23,3]
sum(a[(a.index([i for i in a if i < 0][0]) + 1):])
Evaluates to 34 as expected. Could also add a try/except IndexError with a simple sum to catch if there's no negative value.
Edit: updated the index for the search.
Yes, you can iterate over the elements of the list and keep adding them to some var which would store your result. But what for? sum approach is much more clear and python-ish.
Also, don't use list as a list name, it's a reserved word.
# After you find a first negative number (at i position)
j = i + 1
elements_sum = 0
while j < len(list):
elements_sum += list[j]
j += 1
Not as good as the marked answer, but just to know how to make use of numpy, being sure there is a negative number in the list.
Sample list: lst = [12, 2, -3, 4, 5, 10, 100]
You can get your result using np.cumsum:
import numpy as np
np_lst = np.array(lst)
cum_sum = np.cumsum(np_lst)
res = cum_sum[-1] - cum_sum[np_lst<0][0]
res #=> 119
First of all don't use list as a variable name, it's a reserved keyword. Secondly, make your loop as follows:
for index, x in enumerate(list_):
if x < 0:
sum_ = sum(list_[(index + 1):])
print('Reqemlerin cemi:', sum_)
break
That way, you don't need to find a value.
At last if you don't want to use sum
found_negative = false
sum_ = 0
for x in list_:
if found_negative:
sum_ += x
elif x < 0:
found_negative = true
print('Reqemlerin cemi:', sum_)
I keep getting a "list index out of range" error, but don't know why. Can someone help?
arr = []
if __name__ == '__main__':
x = int(input())
y = int(input())
z = int(input())
n = int(input())
for x in range (x+1):
for y in range(y+1):
for z in range(z+1):
arr.append([x,y,z])
for i in range(len(arr)):
if (arr[i][0] + arr[i][1] + arr[i][2] == n):
del arr[i]
print(arr)
This is happening because you're mutating your list as you traverse through it. In your specific example, you would actually be better off creating a new list from the old list. In this example:
arr = [x for x in arr if (x[0] + x[1] + x[2] != n)]
EDIT: In addition to the comment about the scope of this activity relative to main.
It's better to build a list like this as a comprehension, where you can filter the elements as you build the list rather than having to go back and try to extract them after the fact:
x, y, z, n = (int(input()) for _ in range(4))
arr = [
[i, j, k]
for i in range(x+1)
for j in range(y+1)
for k in range(z+1)
if i + j + k != n
]
That is because you iterate over the len of an array, but that len is computed and stored at the beginning, it isn't update. Let's say the array if of len 5, the loop generates 0,1,2,3,4 but if you delete an item during the loop, when doing arr[4] it'll fail
The best solution is to keep interesting items, not delete the others, whether with another array, or a list comprehension. Also you can iterate of the values of an array, not on indices
# new array
new_vals = []
for v in arr:
if sum(v) != n:
new_vals.append(v)
# list comprehension
arr = [v for v in arr if sum(v) != n]
With my code I would except that after looping one time he will jump to the next number in the list, but he doesn't. Anyone knows what is wrong with my code?
for j in range(len(k)):
s = [int(i) for i in str(k[j])]
This two lines of code are part of a bigger question I am solving.
def kaprekarseries(n):
"""
>>> kaprekar_series(677)
[677, 99, 0]
>>> kaprekar_series(9876)
[9876, 3087, 8352, 6174]
>>> kaprekar_series(55500)
[55500, 54945, 50985, 92961, 86922, 75933, 63954, 61974, 82962]
"""
k = list()
k.append(n)
count = 0
while count < 10:
for j in range(len(k)):
s = [int(i) for i in str(k[j])]
m = sorted(s, key=int, reverse=True)
m2 = int(''.join(str(i) for i in m))
l = sorted(s, key=int)
l2 = int(''.join(str(i) for i in l))
g = m2 - l2
k.append(g)
if [item for item in k if k.count(item) <= 1]:
count += 1
else:
return k
Your list k has just one element being appended prior to starting the loop. Therefore it is list of length of one, therefore it runs just once.
Rethink your algorythm.
I have a long list containing elements that value from 0 to 100.
What I want to do is find all the positions where my elements take on values [0,2]. Then find out all the positions of the values between 2 and 4, etc up to 98 and 100.
Let's call the list containing the values ''list''. And let's call the resulting list p_x. Where x indicates which interval we are finding the positions of.
I managed to get what i want this way:
p_61 = N.where((list >= 60) & (list <= 62))
My question now is: how do i loop this, so that i get as a result all the p_x's that I want?
import itertools
l = list(range(10))
## If you just want the values:
print([(x,y) for (x,y) in itertools.combinations(l, 2) if abs(x-y)==2])
## If you want the positions:
for i, x in enumerate(l):
for j, y in enumerate(l):
if j <= i:
continue
if abs(x-y) == 2:
print(i, j)
## If you want them stored in lists in a dictionary:
d = {}
for i, x in enumerate(l):
for j, y in enumerate(l):
if j <= i:
continue
if abs(x-y) == 2:
k = 'p_{}'.format(x+1)
try:
d[k].append((i,j))
except KeyError:
d[k] = [(i,j)]
I want to find a sequence of n consecutive integers within a sorted list and return that sequence. This is the best I can figure out (for n = 4), and it doesn't allow the user to specify an n.
my_list = [2,3,4,5,7,9]
for i in range(len(my_list)):
if my_list[i+1] == my_list[i]+1 and my_list[i+2] == my_list[i]+2 and my_list[i+3] == my_list[i]+3:
my_sequence = list(range(my_list[i],my_list[i]+4))
my_sequence = [2,3,4,5]
I just realized this code doesn't work and returns an "index out of range" error, so I'll have to mess with the range of the for loop.
Here's a straight-forward solution. It's not as efficient as it might be, but it will be fine unless you have very long lists:
myarray = [2,5,1,7,3,8,1,2,3,4,5,7,4,9,1,2,3,5]
for idx, a in enumerate(myarray):
if myarray[idx:idx+4] == [a,a+1,a+2,a+3]:
print([a, a+1,a+2,a+3])
break
Create a nested master result list, then go through my_sorted_list and add each item to either the last list in the master (if discontinuous) or to a new list in the master (if continuous):
>>> my_sorted_list = [0,2,5,7,8,9]
>>> my_sequences = []
>>> for idx,item in enumerate(my_sorted_list):
... if not idx or item-1 != my_sequences[-1][-1]:
... my_sequences.append([item])
... else:
... my_sequences[-1].append(item)
...
>>> max(my_sequences, key=len)
[7, 8, 9]
A short and concise way is to fill an array with numbers every time you find the next integer is the current integer plus 1 (until you already have N consecutive numbers in array), and for anything else, we can empty the array:
arr = [4,3,1,2,3,4,5,7,5,3,2,4]
N = 4
newarr = []
for i in range(len(arr)-1):
if(arr[i]+1 == arr[i+1]):
newarr += [arr[i]]
if(len(newarr) == N):
break
else:
newarr = []
When the code is run, newarr will be:
[1, 2, 3, 4]
#size = length of sequence
#span = the span of neighbour integers
#the time complexity is O(n)
def extractSeq(lst,size,span=1):
lst_size = len(lst)
if lst_size < size:
return []
for i in range(lst_size - size + 1):
for j in range(size - 1):
if lst[i + j] + span == lst[i + j + 1]:
continue
else:
i += j
break
else:
return lst[i:i+size]
return []
mylist = [2,3,4,5,7,9]
for j in range(len(mylist)):
m=mylist[j]
idx=j
c=j
for i in range(j,len(mylist)):
if mylist[i]<m:
m=mylist[i]
idx=c
c+=1
tmp=mylist[j]
mylist[j]=m
mylist[idx]=tmp
print(mylist)