I want to make changes to a list in-place such that if the list is l1 = [0, 1, A, B], then I can replace the alphabetical values with numbers.
I tried using the following code for it:
for x in l1:
if x == 'A':
x = 10
However, when I look at the list again, it is still the same and A has not been changed to 10. Why is this code not working?
I tried using the indices instead as well, but that did not work either.
for i in range(len(l1)):
if l1[i] == 'A':
l1[i] = 10
In Python things are always passed by value. The 'x' variable in the for loop is a copy of the elements in the list not the pointer/reference of the list elements.
You can change the value of the list by directly indexing it.
One way to achieve that is as follows..
for i,x in enumerate(l1):
If x == 'A':
l1[i] = 10
Assuming A variable points to value 'A' !
Related
I'm trying to make a vector adding of two arrays with the same dimensions, but all that I get is a "list index out of range" error. The code I used is:
x = [0, 0, 0]
y = [1, 2, 3]
i = 0
c = []
while (i <= len(x)):
c.append(a[i] + b[i])
i = i + 1
print c
Can you point me where is te problem? Any help or idea will be appreciated.
In python, try to avoid looping over indices when possible. A more pythonic way of doing this is the following list comprehension
c = [sum(items) for items in zip(x, y)]
list comprehensions allow you to operate on items in an iterable and return a list. zip allows you to iterate over multiple iterables at the same time. This is a good pattern to look out for as you keep learning python
You are iterating both the lists for following index values : [0,1,2,3].
As the length of both the lists is 3, iterating it upto index value 3, won't make any sense because index value begins from 0.
In the condition for while loop, you should change the condition from i <= len(x) to i < len(x).
I want to verify if a member of list, is the sum of the previous numbers.
Example: [0,1,3,4,18,19]. This is TRUE because 0+1+3 = 4
sum_([],0).
sum_([X|XS],R):- suma(XS,R1), R is X + R1.
existsSum(L,[X|C]):-append(A,[X|B],L),
append(A,B,C),
sum_(C,X).
I am stuck here. Any idea? Thanks.
Why append(A,[X|B],L),append(A,B,C),sum_(C,X)? In this way you want the sum of all elements except X to be equal to X.
It is not clear what the arguments of existsSum should be. Supposing existsSum(InputList, SubList, Element):
existsSum(L,A,X) :- append(A,[X|_B],L), sum_(A,X).
With your example produces these results:
?- existsSum([0,1,3,4,18,19], Sublist, Element).
Sublist = [],
Element = 0 ;
Sublist = [0, 1, 3],
Element = 4 ;
false.
Note: also [] and 0 is a solution because of how you defined the sum_ predicate, i.e. the sum of [] is 0.
If you change the sum_ predicate in this way:
sum_([X],X).
sum_([X|XS],R):- sum_(XS,R1),R is X + R1.
it is defined only for non-empty lists, and in this case you get only one result from your example:
?- existsSum([0,1,3,4,18,19], Sublist, Element).
Sublist = [0, 1, 3],
Element = 4 ;
false.
I think your problem is ill-stated (or your example should not start with zero) because I think you basically have two ways you can process the list: either you process the entire list every time (and your example fails because 0+1+3+4+18 != 19) or you stop as soon as your expected value matches the head of the list, in which case [0] is already successful.
In the end, there aren't that many ways to process a list. You have to make a decision when you have an element, and you have to make a decision when you are out of elements. Suppose we want to succeed as soon as we have reached a value that matches the sum-so-far. We can model that fairly simply like this:
exists_sum(List) :- exists_sum(0, List).
exists_sum(RunningTotal, [RunningTotal|_]).
exists_sum(RunningTotal, [H|T]) :-
NewRunningTotal is RunningTotal + H,
exists_sum(NewRunningTotal, T).
Note that with this formulation, [0|_] is already successful. Also note that I have no empty list case: if I make it to the end of a list without having succeeded already, there is no solution there, so there's nothing to say about it.
The other formulation would be to require that the entire list is processed, which would basically be to replace the first exists_sum/2 clause with this:
exists_sum(Total, [Total]).
This will fail to unify exists_sum(4, [4|_]) which is the case you outline in the question where [0,1,3,4...] succeeds.
There may be other formulations that are more complex than these, but I don't see them. I really think there are only a couple ways to go with this that make sense.
This question already has answers here:
How to remove items from a list while iterating?
(25 answers)
Closed 5 years ago.
So, here it is my problem. I'm trying to go over a nested list and delete some elements, according to a condition. The problem is that, whenever one element is deleted, this changes the length of the list which, in turn, creates the error:
IndexError: list index out of range
This is my code:
a = [[[1] * 2 for i in range(n)] for j in range(p)]
for y in range(p):
for x in range(n):
if len(a[y]) > 1:
if a[y][x][1] == 1:
if random.random() < s:
del a[y][x]
With s being just a number between 0 and 1. Because I want to make sure that every list has, at least, 1 value, I'm putting the if len(a[y]) > 1 part. I think I can understand the issue, the issue being that the length of the list is changing and, therefore, the position changes as well. Does anyone know a simple way to overcome this issue?
You need something like a
continue;
or
break;
statement (as for example in Java) that will stop your loop and prevents it to count too far.
So you can only delete one element in each inner loop. After the break; or the continue; you can iterate trough the list again with new list length to delete the second, third.. element if neccessary.
problem link from leetcode
I came up with two solutions wrote in Python but did not pass and do not know why.
Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array),
some elements appear twice and others appear once.
Find all the elements of [1, n] inclusive that do not appear in this
array.
Here is my first solution:
class Solution(object):
def findDisappearedNumbers(self, nums):
nums=sorted(list(set(nums)))
for x in range(1, nums[-1] + 1):
if x in nums:
nums.remove(x)
else:
nums.append(x)
return nums
the result is " Runtime Error Message: Line 4: IndexError: list index out of range". But I did not get it.
The second solution:
return [x for x in range(1, len(nums) + 1) if x not in nums]
The result is "Time Limit Exceeded",still,confused.
Both solutions works okay in my Pycharm with python 2.7.11.Maybe there are some test cases my solutions did not pass but I can not find it.
First of all, try to use xrange instead of range as this uses less space when the value of nums is very large. Also, you are trying to iterate as well as delete/append a value at the same time in the same array. This is most likely the reason why you are getting the error.
Also, removing a value in the list (if it is not at the end) takes a lot of time because all other elements before it need to moved.
From the first solution: DO NOT modify the list you are iterating. Always brings problems. Better copy the list and modify the list!
class Solution(object):
def findDisappearedNumbers(self, nums):
nums=sorted(list(set(nums)))
nums_copy = nums.copy(nums)
for x in range(1, nums[-1] + 1):
if x in nums:
nums_copy.remove(x)
else:
nums_copy.append(x)
return nums_copy
On the other hand, if num is very large (has many elemente)range can bring problems because it creates the list first (and VERY large lists occupy a LOT of memory). For me cases it is better to xrange than to return a generator.
This does not happen in python3, where the default range returns a generator.
You can use nums = set(nums) which will sort and remove all the duplicates. Then you can run a loop to append all the numbers not present in nums to output array.
Your first solution will fail if the test input is an empty list as num[-1] would give an index out of bound.
Your second solution will be slow as it has to iterate through the list. Would the below solution work? Set operations are optimised. But is the space complexity ok for you?
ret = set(range(1, len(nums)+1))
ret = ret - set(nums)
return list(ret)
I have the following pseudocode.
for j in range(0, len(list)):
xx
xx
if something == True:
list.append("x")
Will range(0, len(list)) be called every time j iterates through the block of code, and hence will its max value update?
I tried figuring it out looking at the stack data, however I couldn't figure it out.
No, as range(0, len(list)) is created once at the beginning to create a list (or iterator in python 3), and then it is just iterated though (using next or indexing). It is equivalent to:
list_of_nums = range(0, len(list)) # [0, 1, 2, 3, ...]
for i in list_of_nums:
j = i[counter]
...
Use a while loop like:
j = 0
while j < len(list)):
xx
xx
if something == True:
list.append("x")
j += 1
The iterable is only evaluated once. Since range() on Python 2.x returns a fixed structure the iteration will never be modified once the looping has started. If you need the iteration to change then you will have to use something that doesn't return a fixed structure, such as iterating over the list itself.
range creates a list containing all the element between both arguments - there's nothing magical about it. Once the result is created, it is not modified if the parameters given to range are modified, just like any other function.
Assigning the value of len to a temporary variable will make this more obvious:
tempLen = len(list)
for j in range(0, tempLen):
xx
xx
if something == True:
list.append("x")
No. range is a built-in function. Calling it returns a list. The for statement holds the first return from range and then stops. Try the following:
l = ['a', 'b', 'c']
for j in range(0, len(l)):
l.append(j)
print j
It prints three lines.
BTW, it is not a good idea to assign a variable to list.