How to give a command for the next iteration - python

Im trying to write a code to say that if a condition is met of a value in a list then in the next iteration make that value a different one. the problem is i dont know what the code is to tell python to do it in the next iteration
my code.
list_ = [4, 5, 6, 6, 4, 5]
for i in range(0, 10):
for j in range(0, len(list_)):
if list_[j] == 5:
if list_[(j-1) % len(list)] == 4:
list_[j][i+1] = 3
but this doesnt work as i get a int' object does not support item assignment error. also i know some of the indentation maybe wrong its because i struggled to put them into here

Your exact expected result is not so clear, but anyway I suggest you this solution that seems solving your problem:
list_ = [4, 5, 6, 5, 4, 5]
for j in range(0, len(list_)):
if (list_[j] == 5) and (list_[j-1] == 4):
list_[j] = 3
print(list_)
Note: on the first iteration, list_[j-1] refers to the last element of the list.

Perhaps this will suffice, building a new list according to your logic:
list_ = [4, 5, 6, 6, 4, 5]
lst = []
for i, x in enumerate(list_):
if (x == 5) and (list_[i-1] == 4) and (i-1 > 0):
lst.append(3)
else:
lst.append(x)
lst
# [4, 3, 6, 6, 4, 3]
As a list comprehension:
[3 if (x == 5) and (list_[i-1] == 4) and (i-1 > 0) else x for i, x in enumerate(list_)]
# [4, 3, 6, 6, 4, 3]
The (i-1 > 0) prevents searching the end if 5 is in the first position.
Three main pythonic themes of this implementation:
create a new iterable instead of mutating it
enumerate an iterable to reduce the use of indices
use booleans to chain conditionals rather than nesting conditionals

Related

Why is my code not following the command?

def pairs(x):
for num in x:
if num == num :
return x
y = [2, 2, 2, 2, 2, 4, 3, 3]
pairs (y)
print (y)
this is returning [2, 2, 2, 2, 2, 4, 3, 3]
but I want to return [2,2,3]
I've tried 3 codes already other than this one
help me
Your code seems to be intended to find all the numbers that exist in pairs in the list. The best way would be (for a sorted list) to just cycle through the list and check successive elements.
Your code just matches if the current number is the same as the current numbers always returns true and returns all elements. A correct Code might be:
y = [2, 2, 2, 2, 2, 4, 3, 3]
y=sorted(y) # Sorts the given list
def pairs(arr):
i = 0 # Counter variable
res = [] #result list
while i < len(arr)-1:
if arr[i] == arr[i+1]:
res.append(arr[i]) # If the successive elements are the same, add
# it to the result array and since we have already
# checked the next element, increment the counter by
# two
i+=2
else:
i+=1 # If the elements are different we need to check the
# next element as well so increment by 1
return res
print(pairs(y))
You are comparing the element with itself which is always true. Here is the correct logic
y = [2, 2, 2, 2, 2, 4, 3, 3]
filt = []
i=0
while (i< (len(y)-1)):
if y[i] == y[i+1]:
filt.append(y[i])
i+=1
i+=1
print(filt)

Rotate array in Python

There is this question, 189 Rotate array on Leetcode. enter link description here Its statement is "Given an array, rotate the array to the right by k steps, where k is non-negative."
To understand it better, here's an example.
enter image description here
So, My code for this is
for _ in range(k):
j = nums[-1]
nums.remove(nums[-1])
nums.insert(0, j)
It cannot pass some of the test cases in it.
In the discussion panel, I found a code claiming it got submitted successfully that went like
for _ in range(k):
nums.insert(0, nums.pop(-1))
I would like to know, what is the difference between these two and why my code isn't able to pass some of the test cases.
If you do this on python shell [].remove.__doc__, you'll see the purpose of list.remove is to:
Remove first occurrence of value. Raises ValueError if the value is
not present.
In your code nums.remove(nums[-1]) does not remove the last item, but first occurrence of the value of your last item.
E.g.
If you have a list with values nums = [2, 4, 8, 3, 4] and if you do nums.remove(nums[-1]) the content of nums becomes [2, 8, 3, 4] not [2, 4, 8, 3] that you're expecting.
Just use slicing:
>>> def rotate(l, n):
... return l[-n:] + l[:-n]
...
>>> lst = [1, 2, 3, 4, 5, 6, 7]
>>> rotate(lst, 1)
[7, 1, 2, 3, 4, 5, 6]
>>> rotate(lst, 2)
[6, 7, 1, 2, 3, 4, 5]
>>> rotate(lst, 3)
[5, 6, 7, 1, 2, 3, 4]
In your code j = nums[-1] and you are trying to insert(0, nums[-1]).
In
for _ in range(k):
nums.insert(0, nums.pop(-1))
inserting other number - (0, nums.pop(-1))
Answer given by cesarv is good and simple, but on large arrays numpy will definitely perform better. Consider:
np.roll(lst, n)
The remove() method takes a single element as an argument and removes it's first occurence from the list.
The pop() method takes a single argument (index). The argument passed to the method is optional. If not passed, the default index -1 is passed as an argument (index of the last item).
If the test case has the same item before the last index then test case will fail.
Hence to correct your code replace remove with pop
for _ in range(k):
poppedElement = nums.pop()
nums.insert(0, poppedElement)
or to make it even concise -
for _ in range(k):
nums.insert(0, nums.pop())

How to remove first occurrence of a specific item from a list of items without using .pop() or .remove()

I have a list, let us call it l = [1,2,3,7,8,9,10,7]. Given this list l, I am trying to remove the first occurrence of the number 7 without using the .pop() or .remove() built-in functions.
I have tried
def remove_item(l, item_to_remove):
newlst = []
for item in l:
if item != item_to_remove:
newlst.append(item)
return newlst
However, this removes all instances of the item I am trying to remove when in fact I only want to remove the very first instance of that said specific item. Does anyone have some tips on how to accomplish this??
You only need to take care that the removing part of your code doesn't run twice.
lst = [1,2,3,7,8,9,10,7] # [1, 2, 3, 7, 8, 9, 10, 7]
print(lst)
for i in range(len(lst)):
if lst[i] == 7:
del lst[i] # [1, 2, 3, 8, 9, 10, 7]
break
print(lst)
It does exactly the same as the following:
lst = [1,2,3,7,8,9,10,7]
print(lst) # [1, 2, 3, 7, 8, 9, 10, 7]
for i in range(len(lst)):
if lst[i] == 7:
lst.pop(i)
break
print(lst) # [1, 2, 3, 8, 9, 10, 7]
as well as this
lst = [1,2,3,7,8,9,10,7]
print(lst) # [1, 2, 3, 7, 8, 9, 10, 7]
for i in range(len(lst)):
if lst[i] == 7:
lst.remove(lst[i])
break
print(lst) # [1, 2, 3, 8, 9, 10, 7]
Overview of the used methods:
del list[i] - The del statement can also be used to remove slices from a list
list.pop - remove and return item at index (default last). Raises IndexError if list is empty or index is out of range.
list.remove - remove first occurrence of value.Raises ValueError if the value is not present.
You just need to add a little logic to it. I add a looking variable which signifies that we havent found the entry were looking for. Heres the code
def remove_item(l, item_to_remove):
newlst = []
looking = True
for item in l:
if item != item_to_remove or not looking:
newlst.append(item)
else:
looking = False
return newlst
list = [1,3,4,5,6,7,3,10]
print(remove_item(list, 3))
which returns [1, 4, 5, 6, 7, 3, 10]
Very wasteful, but here you go, a solution:
def remove_first(sequence, element):
return sequence[:sequence.index(element)] + sequence[sequence.index(element)+1:]
Then you can:
>>> remove_first(["a", "b", "a", "c"], "a"):
['b', 'a', 'c']
index returns the index of the first found occurrence of an element.
The rest is sequence splicing and catenation.
Of course, you could generalize this to remove(sequence, element, n) to remove the n-th found element.
EDIT: I just stated falsely that index also supports that. Statement removed.
Or you could choose to mutate the input, but for one, returning the output is cleaner, and you could not have a general "sequence" argument, as not all sequences are mutable. See the tuple type.
.index(x) returns the first index location of x within the list, so just delete it. If x is not found, it returns ValueError.
my_list = [1, 2, 3, 7, 8, 9, 10, 7]
val = 7
if val in my_list:
del my_list[my_list.index(val)]
>>> my_list
[1, 2, 3, 8, 9, 10, 7]
Signature: my_list.index(value, start=0, stop=9223372036854775807, /)
Docstring:
Return first index of value.
Raises ValueError if the value is not present.
Welcome to StackOverflow!
Minor modification to your code,.
I would prefer remove but here is your modified code to do the required job
def remove_item(l, item_to_remove):
newlst = []
for item in l:
if item != item_to_remove:
newlst.append(item)
else:
return newlst + l[len(newlst) + 1 :]
return newlst
In Python, you can add the lists. Using list comprehensions, you select sub-lists(l[len(newlst) + 1 :]).
Testing
>>> list = [1,3,4,5,6,7,3,10]
>>> print(remove_item(list, 3))
[1, 4, 5, 6, 7, 3, 10]
lst = [1,2,3,7,8,9,10,7]
new_lst = lst[:lst.index(7)] + lst[lst.index(7) + 1:]
new_lst
[1, 2, 3, 8, 9, 10, 7]
Similar idea to CEWeinhauer's solution, but one which takes advantage of Python features to minimize overhead once we've found the item to remove:
def remove_item(l, item_to_remove):
newlst = []
liter = iter(l) # Make single pass iterator, producing each item once
for item in liter:
if item == item_to_remove: # Found single item to remove, we're done
break
newlst.append(item) # Not found yet
newlst += liter # Quickly consume all elements after removed item without tests
return newlst
The above works with any input iterable in a single pass, so it's better if the input might not be a list and/or might be huge. But it's admittedly more complex code. The much simpler solution is to just find the element with index and remove it. It might be slightly slower in some cases, since it's two O(n) steps instead of just one, but it uses C built-ins more, so it's likely to be faster in practice:
def remove_item(l, item_to_remove):
newlst = list(l)
del newlst[newlst.index(item_to_remove)]
return newlst

How to increase efficiency of comparing elements of a list?

Whenever I code on online platforms and somehow I have to compare the elements of a list to one another, I use the following code which according to me is the most efficient possible. This is the last code which I was practicing. It was to find the maximum index between 2 same elements.
max=0
for i in range(len(mylist)):
if max==(len(mylist)-1):
break
for j in range(i + 1, len(mylist)):
if mylist[i] == mylist[j]:
if max>(abs(i-j)):
max=abs(i-j)
It runs most of the test cases, but sometimes it shows "time limit exceeded." I know it is related to the constraints and time complexity but I still can't find a better way. If anyone could help me, that would be great.
It's easier to use C based functions in Python. Also don't name variables python types like list.
x = [item for i, item in enumerate(l) if item in l[i+1:]]
# do something with list of values
You could group by equal elements and then find the difference in-group, and keep the maximum:
lst = [1, 3, 5, 3, 7, 8, 9, 1]
groups = {}
for i, v in enumerate(lst):
groups.setdefault(v, []).append(i)
result = max(max(group) - min(group) for group in groups.values())
print(result)
Output
7
The complexity of this approach is O(n).
def get_longest_distance_between_same_elements_in_list(mylist):
positions = dict()
longest_distance = 0
if len(mylist) < 1:
return longest_distance
for index in range(0, len(mylist)):
if mylist[index] in positions:
positions[mylist[index]].append(index)
else:
positions[mylist[index]] = [index]
for key, value in positions.items():
if len(value) > 1 and longest_distance < value[len(value)-1] - value[0]:
longest_distance = value[len(value)-1] - value[0]
return longest_distance
l1 = [1, 3, 5, 3, 7, 8, 9, 1]
l2 = [9]
l3 = []
l4 = [4, 4, 4, 4, 4]
l5 = [10, 10, 3, 4, 5, 4, 10, 56, 4]
print(get_longest_distance_between_same_elements_in_list(l1))
print(get_longest_distance_between_same_elements_in_list(l2))
print(get_longest_distance_between_same_elements_in_list(l3))
print(get_longest_distance_between_same_elements_in_list(l4))
print(get_longest_distance_between_same_elements_in_list(l5))
Output -
7
0
0
4
6
Time Complexity : O(n)

Recursively rearrange a sequence of integers from even to odd

This is a practice problem that I've been trying to solve for a while:
Write a recursive Python function that rearranges a sequence of integer values so that all the even values appear before all the odd values.
What I have:
def arrange(x):
even = ''
odd = ''
y = str(x)
if y == '':
return y
elif int(y[0]) % 2 == 0:
even += y[0]
if y[1:] != '':
arrange(int(y[1:]))
else:
odd += y[0]
if y[1:] != '':
arrange(int(y[1:]))
final = int(even + odd)
After running the visualizer, I think the problem in the code lies within the fact that even and odd are reset everytime. Though, I need it all to be in one function. Any advice?
EDIT: Completed in case anyone wanted to use the same practice problem -
even = []
odd = []
def arrange(x):
y = str(x)
if y == '':
return y
elif int(y[0]) % 2 == 0:
even.append(y[0])
if y[1:] != '':
arrange(int(y[1:]))
else:
odd.append(y[0])
if y[1:] != '':
arrange(int(y[1:]))
def complete(x):
evens = ''
odds = ''
arrange(x)
for i in even:
evens += i
for i in odd:
odds += i
return int(evens + odds)
Disclaimer
I do not know any python. I am answering this question as much as a learning exercise for me as the problem is an exercise for you.
I have not checked this answer for syntax errors.
I think your hunch that the problem is due to even and odd being reset on each call is correct - you need to pass them in to rearrange. Here is my attempt:
def arrange(x, evenInput, oddInput):
even = str(evenInput)
odd = str(oddInput)
y = str(x)
if y == '':
return y
elif int(y[0]) % 2 == 0:
even += y[0]
if y[1:] != '':
arrange(int(y[1:]), even, odd)
else:
odd += y[0]
if y[1:] != '':
arrange(int(y[1:]), even, odd)
final = int(even + odd)
I have a different solution, it isn't very efficient if you're working with larger lists*, but I guess for an assignment it's fine:
def evenBeforeOdd(x):
if not x:
return []
if x[0] % 2 == 0: #even
return [x[0]] + evenBeforeOdd(x[1:])
else:
return evenBeforeOdd(x[1:]) + [x[0]]
*: If I remember correctly, adding lists together is pricy (O(n), plus the slicing, which is O(1) in our case, I think), which it needs to do for each item of the list, so the whole thing should be O(n^2). Also it's not very memory efficient, since it must create new lists all the time.
If I actually wanted to solve the problem without the recursivity requirement, it'd simply be something like this:
sorted(myList, key=lambda x: x%2!=0)
Here's a simple solution. For a given index ind recursively apply func for the list, ind ownwards, followed by checking whether the value at ind is even or odd. If odd, just move that value to the end of the list.
When the recursion starts to unwrap, it will begin rearrangement from the end of list and as the stack unwinds, the pervious elements of the list would start to fall in the right places.
def func(lst, ind=0):
if ind < len(lst):
func(lst, ind+1)
if lst[ind] % 2 != 0:
lst.append(lst.pop(ind))
return lst
print func([3,4,6,2,1])
I wasn't sure what your desired output was, or if you wanted it to recurse and keep the structure/order. Here's a swiss army knife.
from pprint import pprint
def even_before_odd(values, keep_structure=False, sort=False):
evens, odds = even_odd(values, keep_structure, sort)
return evens + odds
def even_odd(values, keep_structure=False, sort=False):
evens = []
odds = []
for value in values:
if isinstance(value, list):
_evens, _odds = even_odd(value, keep_structure, sort)
if keep_structure:
# This will insert a sub array
evens.append(_evens)
odds.append(_odds)
else:
# This will append them to the list
evens += _evens
odds += _odds
continue
if value % 2 == 0:
evens.append(value)
else:
odds.append(value)
if sort:
evens = sorted(evens)
odds = sorted(odds)
return evens, odds
values = []
for x in range(0,10):
values.append(list(range(0,10)))
result = even_before_odd(values, False, True)
print "result 1:", ",".join(map(str, result))
result = even_before_odd(values, False, False)
print "result 2:", ",".join(map(str, result))
print "result 3:"
result = even_before_odd(values, True, True)
pprint(result)
Output:
result 1: 0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,6,6,6,6,6,6,6,6,6,6,8,8,8,8,8,8,8,8,8,8,1,1,1,1,1,1,1,1,1,1,3,3,3,3,3,3,3,3,3,3,5,5,5,5,5,5,5,5,5,5,7,7,7,7,7,7,7,7,7,7,9,9,9,9,9,9,9,9,9,9
result 2: 0,2,4,6,8,0,2,4,6,8,0,2,4,6,8,0,2,4,6,8,0,2,4,6,8,0,2,4,6,8,0,2,4,6,8,0,2,4,6,8,0,2,4,6,8,0,2,4,6,8,1,3,5,7,9,1,3,5,7,9,1,3,5,7,9,1,3,5,7,9,1,3,5,7,9,1,3,5,7,9,1,3,5,7,9,1,3,5,7,9,1,3,5,7,9,1,3,5,7,9
result 3
[[0, 2, 4, 6, 8],
[0, 2, 4, 6, 8],
[0, 2, 4, 6, 8],
[0, 2, 4, 6, 8],
[0, 2, 4, 6, 8],
[0, 2, 4, 6, 8],
[0, 2, 4, 6, 8],
[0, 2, 4, 6, 8],
[0, 2, 4, 6, 8],
[0, 2, 4, 6, 8],
[1, 3, 5, 7, 9],
[1, 3, 5, 7, 9],
[1, 3, 5, 7, 9],
[1, 3, 5, 7, 9],
[1, 3, 5, 7, 9],
[1, 3, 5, 7, 9],
[1, 3, 5, 7, 9],
[1, 3, 5, 7, 9],
[1, 3, 5, 7, 9],
[1, 3, 5, 7, 9]]
Here is an efficient, short way to do this (not recursive however).
A string in Python is an iterable, so there actually is no need to keep taking substrings of the original input. Instead, you could filter out the odd and even digits and later concatenate them.
def splitEvenOdd(x):
even = [e for e in x if int(e)%2 == 0]
odd = [o for o in x if int(o)%2 == 0]
even = "".join(even)
odd = "".join(odd)
return even + odd

Categories

Resources