inserted list changes even after being inserted - python

I wanted to create a list of lists
def func(m,n,l,t):
a=[i for i in range(m)]
b=[]
b.append(a)
a=swap(a)
b.append(a)
for i in b:
print(i)
def swap(l):
i,n=0,len(l)
while(i<n):
l[i],l[i+1]=l[i+1],l[i]
i+=2
return l
i created list a as my basis and append each modification i want to in the b list.
The problem is after i append the first list and modify it, the first one i inserted also changes the same as the second one i inserted.
the output of this code is this
[1, 0, 3, 2, 5, 4, 7, 6]
[1, 0, 3, 2, 5, 4, 7, 6]
what i want is when i performm the swap i dont want the first list to change
the output should look like this
[0, 1, 2, 3, 4, 5, 6, 7]
[1, 0, 3, 2, 5, 4, 7, 6]
if you could help, please thank you.

In place of append() method, you can try out extend() method which does the same as of append. but extend() method is mainly used for iterate items, as of in your case.
and also if you want to use only append, then take a copy of your variable first and append it, as you are changing in the first place, it is taking effect in the list too. So you can follow append into a list like, a.copy(). Hopes it helps
Please try out and share the feedback.
Thank you

Their are multiple code error you have done, for example:
you don't have to iterate over range object in order to get list, you could just...
a = list(range(m))
and also You don't have to run a while loop in order to iterate over two steps you could...
for i in range(0, len(l), 2):
see range for reference
also you didn't use any of n, l, t parameters of the func function.
THE ANSWER
when you pass the a variable to the swap function you are actually passing the class Object itself, so the swap function can change the value of the a variable (list class).
All you need is passing a copy of the a variable not the variable itself
a = swap(a.copy())
FINAL CODE
def swap(l):
for i in range(0, len(l), 2):
l[i],l[i+1]=l[i+1],l[i]
return l
def func(m):
a = list(range(m))
b = [a]
a = swap(a.copy())
b.append(a)
for i in b:
print(i)
func(8) # [0, 1, 2, 3, 4, 5, 6, 7], [1, 0, 3, 2, 5, 4, 7, 6]

Related

What to do if a variable is in the for loop statement?

I'm just wondering what would happen if a variable is the for loop (or while loop) statement. Will that variable only be evaluated the first time that statement is executed?
For example:
arr = [2, 3, 4]
for i in range(len(arr)):
arr.append(5)
Yes. Try it:
>>> arr = [2, 3, 4]
>>>
>>> for i in range(len(arr)):
... arr.append(5)
...
>>> arr
[2, 3, 4, 5, 5, 5]
As you can see, the loop has 3 iterations, because that's the value of len(arr) at the start of the loop.
This is the exact reason that it's generally discouraged to modify a list (or any other iterable) as you're iterating over it; the results may not always be intuitive since the iterator is set up at the start of the loop, and modifying the list may cause it to behave in unexpected ways (skipping over items, etc).
Will that variable only be evaluated the first time that statement is
executed?
Yes, if I understand your question correctly, the expression in the header of the for loop is only evaluated once. You can verify this by creating your own function that prints a message then returns the length of the array.
def my_fun(my_list):
print("Inside my function.")
return len(my_list)
arr = [2, 3, 4]
for i in range(my_fun(arr)):
arr.append(5)
print(arr)
Output:
Inside my function.
[2, 3, 4, 5, 5, 5]
As you can see, the message is only printed one time, so range(my_fun(arr)) must only be evaluated one time.
The code here is equivalent to :
arr = [2, 3, 4]
r = range(len(arr))
for i in r:
arr.append(5)
print(arr)
Here the call to the range function generates a new object of type range (https://docs.python.org/3/library/stdtypes.html#typesseq-range). The iteration through the for loop is therefore on the object r, and not on the object arr. The modification in the loop of arr has therefore no consequences on the loop itself, since this one is on the object r.
On the other hand, if we try the following code :
arr = [2, 3, 4]
for i in arr:
arr.append(5)
if len(arr) > 15:
break
print(arr)
We get the following result:
[2, 3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5]
Here the for loop is applied directly on arr, and so its modification does impact the iteration performed by the for.

How to append values to list?

I want to append my list with values for each loop iteration:
for i in range (4,10):
a_list = [1,2,3]
a_list = a_list.append(i)
The wanted output would be [1,2,3,4,5,6,7,8,9]. But I get None. Also printing type(a_list) after using .append() gives me <class'NoneType'>. What is the problem here ?
firstly, you have to mention a_list before for. instead, you will get [1, 2, 3, 9]. secondly, you give the a_list a value of a_list.append() function.
a_list = [1, 2, 3]
for i in range(4, 10):
a_list.append(i)
it is mainly because of the fact that list.append method does not return anything, it appends the given value to the list in-place.
we can confirm this by the simple example below
a = list()
b = a.append(5)
>> print(b)
None
>> print(a)
[5]
As matter of fact,there is a simpler and more performant way to achieve this
>> a_list = [1,2,3]
>> a_list += list(range(4, 10))
>> print(a_list)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Here, we first shape a new list from a iterator range(4, 10),
then we concate the two list together to get the list we want by adding the new list to the original list a_list.
by doing this, we can avoid the overhead caused by repeatedly call the list.append method in a for loop
a_list = []
for i in range (1,10):
a_list.append(i)
print(a_list)
Output
[1, 2, 3, 4, 5, 6, 7, 8, 9]
You have the wrong indentation on the loop.You need to add i at each iteration. Also, to get the list you want, you need to add 1, then 2, then 3, and so on. i this is what needs to be added. Put print(i) and print each iteration.
a_list = [1,2,3]
for i in range (4,10):
a_list.append(i)
print(a_list)
If you use your option, it will be correct to declare an array once. And then only add values. See below.
[1, 2, 3, 4, 5, 6, 7, 8, 9]

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 modify a variable in a class function

So i got this function. It must not be changed!
class TestUnikati(unittest.TestCase):
def test_02_clean(self):
s = [5, 4, 1, 4, 4, 4, 4, 4, 3]
unique_array(s) #<-- calls the function
self.assertEqual(s, [5, 4, 1, 3])
Basically we test if the function clean() only returns a unique array. The variable s being the array.
This is my function that get's the messy array s and tries to return an array of no duplicate elements
def unique_array(s):
s=unique(s) #<-- this is a function that just returns a unique array
x=TestUnikati() #<-- I store the class in the x variable
[insert a way to push s to the "TestUnikati.test_02_clean.s"]
I tried many things. I've tried some experiments with globals() and locals() as well as many things with the x object variable but I don't seem to get it right.
I've tried to push it to the locals() of TestUnikati.test_02_clean.s with the x object. Is there a way to save it so the s in the class function will be over-ridden and the self.assertEqual(s, [5, 4, 1, 3]) will compare the 2 and pass it? Something like this:
x.test_02_clean.s=unique(s)
or
x.s=unique(s)
As others have stated, since test_02_clean() doesn't assign the results of its call of unique_array() to anything, it's expecting you to mutate the given list in place. Something like this:
def unique_array(s):
# Keep a set of all the items we've seen so far
seen = set()
# Index into list
i = 0
while i < len(s):
if s[i] in seen:
# Delete element from list if we've already seen it
del s[i]
else:
# Or else add it to our seen list and increment the index
seen.add(s[i])
i += 1
>>> s = [5, 4, 1, 4, 4, 4, 4, 4, 3]
>>> unique_array(s)
>>> s
[5, 4, 1, 3]
you must have to change your class variable to access globally like below:-
class TestUnikati(unittest.TestCase):
def test_02_clean(self):
self.s = [5, 4, 1, 4, 4, 4, 4, 4, 3]
unique(self.s) <-- calls the function
self.assertEqual(self.s, [5, 4, 1, 3])
and also to reassign it with shorted value you have to do like:-
self.s=unique(s)
You need a function unique() that changes the list in place, instead of returning a new list, e.g.
def unique(l):
count = {}
for entry in l:
count[entry] = count.get(entry, 0) + 1
for entry in l:
for _ in range(count[entry] - 1):
l.remove(entry)
This works in place:
a = [1, 1, 1, 3, 4, 2]
unique(a)
print(a)
>>> [1, 3, 4, 2]

function that concatenates two lists python Codecademy

I am stucked at ex 18,chapter lists and function from CODECADEMY.
"Create a function called flatten that takes a single list and concatenates all the sublists that are part of it into a single list."
"1 On line 3, define a function called flatten with one argument called lists.
2 Make a new, empty list called results.
3 Iterate through lists. Call the looping variable numbers.
4 Iterate through numbers.
5 For each number, .append() it to results.
6 Finally, return results from your function."
Here is my code:
And the error:
Oops, try again. flatten([[1, 2], [3, 4]]) returned [1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4] instead of [1, 2, 3, 4]
n = [[1, 2, 3], [4, 5, 6, 7, 8, 9]]
# Add your function here
results=[]
def flatten(lists):
for numbers in lists:
for number in numbers:
results.append(number)
return results
print flatten(n)
I can't figure out what is wrong.
Your mistake is that you declared the results list globally, while you should have declared it in the scope of your function.
Because results is outside of the function, it doesn't reset when you run flatten() the second time. Instead, the newly flattened array is added on top of the one from the previous run.
You should move results inside your function like so:
def flatten(lists):
results[]
for numbers in lists:
for number in numbers:
results.append(number)
return results
That way it resets every time you run the function and thus returns the correct result.
Convert this:
results=[]
def flatten(lists):
to this:
def flatten(lists):
results=[]
Is you data input wrong?
If you replace you first line of code
n = [[1, 2, 3], [4, 5, 6, 7, 8, 9]]
with
n = [[1, 2], [3, 4]].
The output will be
[1, 2, 3, 4]
Also, you should place results=[] inside function def flatten(lists):
def flatten(lists):
results=[]
for numbers in lists:
for number in numbers:
results.append(number)
return results

Categories

Resources