Alternatives to index() in Python - python

So for my assignment I must find a way in which I can work around this problem of printing 'YES' if a list contains the elements 1,2,3 in the consecutive order. It does not work if the list contains the elements [3,1,2,3] due to the index method. How can I work around this?
n=int(input("Enter the number of elements: "))
A=[]
for i in range(0,n):
print("Entering element", i)
LstEl=int(input("Please enter the element: "))
A.append(LstEl)
print(A)
for i in range(0,len(A)):
if(1 in A and 2 in A and 3 in A):
post1 = A.index(1)
post2 = A.index(2)
post3 = A.index(3)
if(post1 < post2 and post2 < post3):
print("YES")
break
else:
print('NO')
break
else:
print("NO")
break
Thanks!

one option is just:
# find the indices of all `1`s
one_idxs = (i for (i, v) in enumerate(values) if v == 1)
for idx in one_idxs:
if values[i : i + 3] == [1, 2, 3]:
print('YES')
break
else:
print('NO')
a more concise way is
if any(values[i : i + 3] == [1, 2, 3] for (i, v) in enumerate(values) if v == 1):
print('YES')
else:
print('NO')

Once you find a valid post1 value, you can check for the sequence using
if A[post1:post1+3] == [1, 2, 3]:
print('Yes')
break
Use the other parameters of the index() method to find successive occurrences of the element '1'.

The following code uses a generator function to extract sublists from a larger list. It's probably not appropriate for a homework assignment if you don't understand the mechanics behind generator functions, but it might be something to look into if you're interested.
# A generator function that returns the n-length sublists of list lst
def slider(lst, n):
start = 0
while start + n <= len(lst):
yield lst[start:start+n]
start += 1
# A function that will return True if sequence needle exists in
# haystack, False otherwise
def list_contains(haystack, needle):
for sub in slider(haystack, 3): # Loop through the sublists...
if sub == needle: # ... test for equality ...
return True
return False
# Code
big = [2,4,6,8,0,1,2,3,1,5,7] # Hardcoded here, could be created
# in a loop like you show
seq = [1,2,3] # The sequence you're looking for
print(list_contains(big, seq))
You can see the output of the generator function with something like:
big = [2,4,6,8,0,1,2,3,1,5,7]
for sub in slider(big, 3):
print(sub)
Output:
[2, 4, 6]
[4, 6, 8]
[6, 8, 0]
[8, 0, 1]
[0, 1, 2]
[1, 2, 3]
[2, 3, 1]
[3, 1, 5]
[1, 5, 7]
Or maybe more clearly:
# [2, 4, 6, 8, 0, 1, 2, 3, 1, 5, 7]
[2, 4, 6]
[4, 6, 8]
[6, 8, 0]
[8, 0, 1]
[0, 1, 2]
[1, 2, 3]
[2, 3, 1]
[3, 1, 5]
[1, 5, 7]

I would suggest using enumerate with the for loop.
lst = ['a', 'b', 'c', 'd']
for i, value in enumerate(lst):
print(i, value) # 0,a.....3,d

Related

Need to remove all duplicated values in list

I am trying to solve this question "Good array is the array that does not contain any equal adjacent elements.
Given an integer array A of length N, you are asked to do some operations (possibly zero) to make the
array good. One operation is to remove two equal adjacent elements and concatenate the rest of the array.
A : (1, 2, 2, 3, 4)
An after-one operation : (1, 3, 4)
" With python list, as follow:
L=[]
n=int(input("Enter a num"))
for _ in range(n):
x=int(input())
L.append(x)
print(L)
for z in range(L):
if L[z]==L[z+1]:
L.remove(z)
L.remove(z+1)
print(L)
I keep getting this error: Input In [37]
if L[z]==L[z+1]
^
SyntaxError: invalid syntax
any solutions!!`
Easiest solution is to groupby the array and just keep the groups with only one item:
>>> A = [1, 2, 2, 3, 4]
>>> import itertools
>>> A = [i for i, g in itertools.groupby(A) if len(list(g)) == 1]
>>> A
[1, 3, 4]
Edit
This is NOT correct solution of the above problem. It removes contiguous duplicates from the list. But in question, we need to keep 1 instance of duplicate element.
Please refer to #funnydman solution. Thanks #funnydman for pointing out the mistake :)
You are iterating the list and deleting items from the same :|
Not a good idea!
You can use another list to store the result.
result = []
for z in range(len(L)-1):
if L[z]!=L[z+1]:
result.append(L[z])
result.append(L[-1])
Unfortunately, Nawal's solution does not produce the correct answer, I would suggest this approach:
def get_good_array(alist):
result = []
L = alist + [None]
i = 0
while i < len(L) - 1:
if L[i] != L[i + 1]:
result.append(L[i])
i += 1
else:
i += 2
return result
assert get_good_array([1, 2, 2, 3, 4]) == [1, 3, 4]
assert get_good_array([1, 1, 2, 2, 3, 4]) == [3, 4]
assert get_good_array([0, 1, 1, 2, 2, 3, 4]) == [0, 3, 4]
assert get_good_array([1, 3, 4, 4]) == [1, 3]
assert get_good_array([1, 3, 4, 4, 5]) == [1, 3, 5]
You are missing a : at the end of the if statement, your code should look like the following
L=[]
n=int(input("Enter a num"))
for _ in range(n):
x=int(input())
L.append(x)
print(L)
for z in range(L):
if L[z]==L[z+1]:
L.remove(z)
L.remove(z+1)
print(L)
I guess using <list>.count() is quite intuitive approach. As following,
def deduplicate(l: list):
return [value for value in l if l.count(value) == 1]
assert deduplicate([2]) == [2]
assert deduplicate([2, 2]) == []
assert deduplicate([2, 2, 3]) == [3]
assert deduplicate([2, 2, 2]) == []
assert deduplicate([2, 2, 2, 3]) == [3]

How to get the next i that meets the condition under the if not condition in Python?

My problem is a bit difficult to describe, I want to use an example to show my problem.
For example, each number corresponds to a corresponding value,
a=[0,3,5]
b=[0,1,2,3,4,5,6,7]
for i in range(b):
if i not in a:
if ***value of i < value of next i that meet the condition***
a.append(i)
else:
a.append(***next i that meet the condition***)
I want to write code like this but the problem is that I don't know how to express the next i that meet the condition. Simply use i+1 is definitely wrong. Can somebody help me? Thank you very much, guys!!
Adjusting the range for your loop makes it easier to access the current and next element of b:
a = [0, 3, 5]
b = [0, 1, 12, 2, 16, 3, 18, 4, 20, 5, 22]
for index in range(1, len(b) - 1):
current_item = b[index - 1]
next_item = b[index]
if current_item in a:
continue
if current_item < next_item:
a.append(current_item)
else:
continue
print(a)
Out:
[0, 3, 5, 1, 2, 4]
You didn't mention about additional restrictions so there are no checking if our lists are empty or contain just 1 element.
You can consider using this:
a = [0, 3, 5]
b = [0, 1, 2, 3, 4, 5, 6, 7]
for i in range(len(b) - 1):
if (b[i] < b[i + 1]) and b[i] not in a:
a.append(b[i])
print(a)
And this is another version if you don't want to use "i+1":
a = [0, 3, 5]
b = [0, 1, 2, 3, 4, 5, 6, 7]
for n, m in zip(b[:-2], b[1:]):
if n < m and n not in a:
a.append(n)
print(a)

How to create an output list which is the sum of alternating elements from an input number_list

I'm trying to sum the even and odd-indexed elements of a list together without the use of the sum() method, but something is going wrong. I'm new to Python so help would be appreciated.
An example would be input number_list as [1, 2, 3, 4] then the output list will be [4, 6], which is from the sum of the even-numbered elements 1 and 3, and the odd-numbered elements 2 and 4 from the list number_list. Similarly, [5, 8, 3, 2, 6, 7, 1] would have an output list of [8, 10, 9, 9, 5].
This is my code:
number_list = [2, 6, 3, 5, 9, 1, 7]
res=[0, 0, 0, 0, 0, 0]
for i in range(0, len(number_list)):
if(i % 2):
res[1] += number_list[i]
else :
res[0] += number_list[i]
print("Input List: {0}\n".format(number_list))
print("Output List: {0}\n".format(res))
I think the following is what you were going for; your first attempt was definitely on target:
!/usr/bin/env python3
number_list = [2, 6, 3, 5, 9, 1, 7]
i = 0
r = [0,0]
for n in number_list:
if (i % 2) == 0:
# Even
r[0] += n
else :
# Odd
r[1] += n
i += 1
print(" Input List: {0}". format(number_list))
print("Output List: {0}". format(r))
The result is:
Input List: [2, 6, 3, 5, 9, 1, 7]
Output List: [21, 12]
There are some simplifications here, namely throwing out Python nuances and just looking at iterating over a list of numbers, determining whether they are in the even or odd position (the i index), and adding (summing) them to the base r array. Is this the most compact and optimized Python code you will encounter? No. But is it clear as to what you're trying to do - I think so.
Joe's answer is absolutely correct. However more compact answer would be..
r = [0,0]
for n, val in enumerate(number_list):
j = n % 2
r[j] += val
print(" Input List: {0}". format(number_list))
print("Output List: {0}". format(r))

for loop, lst[i] = lst[i - 1] - Python

Why doesn't this work?
def func(lst):
for i in range(len(lst)):
lst[i] = lst[i - 1]
return lst
print(func([1, 2, 3, 4]))
Expected output: [4, 1, 2, 3]
Actual output: [4, 4, 4, 4]
why python assign lst[1] = lst[-1] when it should be lst[1] = lst[0]
The following works. lst[i] was reset in the for loop.
def func(lst):
output = []
for i in range(len(lst)):
output.append(lst[i - 1])
return output
print(func([1, 2, 3, 4]))
Swapping has been proposed. Don't do that:
def func(l):
for i in range(len(l) // 2):
l[i], l[-i - 1] = l[-i - 1], l[i]
return l
# func([1, 2, 3, 4]) -> [4, 3, 2, 1]
To move the last element of a given list/array to the first position, as you've described as your desired output, use blhsing's implementation, if your input is a linked list. Python lists are linked lists, and so blhsing's implementation is an efficient one for those. If your input is a contiguous array, like a Numpy array, use this:
def func(l):
l_last = l[len(l) - 1]
for i in range(len(l) - 1, 0, -1):
l[i] = l[i - 1]
l[0] = l_last
return l
Both of our implementations mutate the input list/array.
Why does your function output [4, 4, 4, 4]?
i_max = len(<list>) - 1
<list>[-i] = <list>[len(<list>) - i].
for i in range(len(<list>)) => i_n in {0, 1, ..., i_max}
i_n = 0 => <list>[0] = <list>[i_max - 1].
If <list> = [1, 2, 3, 4], then [1, 2, 3, 4][0] = [1, 2, 3, 4][3] = [4, 2, 3, 4].
In the next iterations, you will repeatedly replace the ith with the i-1th element, so that you get:
[4, 2, 3, 4] => [4, 4, 3, 4] => [4, 4, 4, 4] => [4, 4, 4, 4].
You got a logic error here, at first iteration you doing smth like lst[0] = lst[-1] and then pulling this value to all remaining indeces. If you want to shift array left one pos try something like this:
def shifter(lst):
return lst[-1:] + lst[:-1]
Lists are mutable objects and you are iterating over a single list. On each iteration, the variable lst is pointing to the current state of the list, and inside your loop you are modifying that current state.
Your expected answer would require that Python would copy and remember the initial state of the list at the beginning of the loop, which Python does not do.
def func(lst):
initial = lst[:] # copy lst
for i in range(len(lst)):
lst[i] = initial[i - 1]
return lst
print(func([1, 2, 3, 4]))
def func(lst):
for i in range(len(lst)):
print(i, lst[i-1])
lst[i] = lst[i - 1]
return lst
If you look at how your code executes, the first iteration, i will be 0, and lst[i-1] will be lst[-1] which points to the last element in the array (4). So after first iteration, your array looks likes this:
[4,2,3,4]
In the second, i=1, and lst[i-1] will be lst[0] which has a value a 4 now! So now lst[1] will be 4:
[4,4,3,4]
And so on....
Hope that helps.
You can insert the last item at the first index and delete the last item afterwards:
def func(lst):
lst[:0] = lst[-1:]
del lst[-1:]
return lst
so that func([1, 2, 3, 4]) returns: [4, 1, 2, 3]
Step through your code, one line at a time:
Initially, lst is [1, 2, 3, 4], so len(lst) is 4. range(n) returns values form 0 to n - 1, so your loop will run with the values 0, 1, 2, and 3.
First loop iteration:
i is 0
lst[i] = lst[i - 1] => lst[0] = lst[0 - 1] => lst[0] = lst[-1]
lst is now [4, 2, 3, 4]
Second loop iteration:
i is 1
lst[i] = lst[i - 1] => lst[1] = lst[1 - 1] => lst[1] = lst[0]
lst is now [4, 4, 3, 4]
Third loop iteration:
i is 2
lst[i] = lst[i - 1] => lst[2] = lst[2 - 1] => lst[2] = lst[1]
lst is now [4, 4, 4, 4]
Fourth loop iteration:
i is 3
lst[i] = lst[i - 1] => lst[3] = lst[3 - 1] => lst[3] = lst[2]
lst is now [4, 4, 4, 4]

List append in recursion

I am unable to make a pascal triangle. I need to append to list elements in recursion, but the result of my work is list appending in list. Can u help me to do it?
My testing code is:
def list(row):
if(row is 0):
return 0
return [row, list(row-1)]
If I use it, I will return list in list. I need elements in list
print(list(10))
Output:
[10, [9, [8, [7, [6, [5, [4, [3, [2, [1, 0]]]]]]]]]]
Expected output:
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
Regarding your specific function, here's one way you could write it
def foo (row):
if row == 0:
return [0]
else:
return [row] + foo (row - 1)
print(foo(10))
# [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
Perhaps a more "pythonic" way of writing that would be
print([10 - x for x in range (0, 11)])
# [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
Regarding pascal's triangle, here's one way you can write the program using an auxiliary helper and continuation passing style – for those wondering, this choice was made so that the result could be assembled in a straightforward manner and the recursive call is in tail position, meaning this function could easily be put on a trampoline to be made stack-safe if necessary
def sliding (n,xs):
if n > len(xs):
return []
else:
return [xs[0:n]] + sliding(n, xs[1:])
def pascal (n):
def aux (m, prev, k):
if n == m:
return k([prev])
else:
return aux(m + 1, [1] + [x + y for (x,y) in sliding(2, prev)] + [1], lambda rest: k([prev] + rest))
return aux(1, [1], lambda x: x)
for line in pascal(5):
print(line)
# [1]
# [1, 1]
# [1, 2, 1]
# [1, 3, 3, 1]
# [1, 4, 6, 4, 1]
What you want is probably this:
return [row] + list(row-1)
This creates a list with one element row and adds the other list on top of it.
It sounds like you want to concatenate the list [x] with the list returned as a result of calling list(x-1). The nice thing about lists in python is that the + operator does exactly this. If we change the final return statement to return [x] + list(x-1) we're headed in the right direction. You'll then notice that you run into trouble when x is 0 becuase you cant add a list to an integer, so you'll want to change your base case to return [0]. Finally, as mentioned, it's best to avoid declaring names that overwrite python built in functions (list is one), so let's rename your function to my_list:
def my_list(row):
if row == 0:
return [0]
return [row] + my_list(row-1)
This doesn't quite get you to pascal's triangle, but hopefully you're off on the right course.
You can create a recursive range function that outputs your expected results:
def rec_range(n):
return [n] + rec_range(n-1) if n else [0]
>>> rec_range(10)
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
Hope it helps.
Or just use range (xrange in python2.x):
>>> list(range(10+1))[::-1] # reverse the list
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
You can create a Pascal's triangle using the given way
def pascal(rows):
for i in range (rows):
value=1
List = [value]
for j in range (i):
value = value * ( i-j ) * 1 / ( j + 1 )
List.append(int(value))
print(List)
pascal(5)
# [1]
# [1, 1]
# [1, 2, 1]
# [1, 3, 3, 1]
# [1, 4, 6, 4, 1]

Categories

Resources