can i not do - if nums[i] == nums[i+]: in python - list

I am new to programming and python. (ref to code below) - I am trying to compare the elements in a list to eliminate duplicates in adjacent numbers in the list (so that all numbers in the resulting list are unique). I actually dont hit the nested "if" statement because this code skips the internal if. However when i try it without the external if, I get an error: File "list2.py", line 22, in remove_adjacent
if nums[i] == nums[i+1]:
TypeError: list indices must be integers, not tuple
def remove_adjacent(nums):
x = len(nums)
print x
for i in enumerate(nums):
if i < x-1:
if nums[i] == nums[i+1]:
del nums[i]
return

It should be for i in range(len(nums)). enumerate returns key/value tuple - which is not integer, as error message says.

Related

How to solve a "list index out of range" trying to make a vector adding?

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).

[Leetcode]448. Find All Numbers Disappeared in an Array

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)

How to put in a range for a variable

def getPoints(n):
if n==1:
return [1,11]
elif n==(range(2,10)):
return [n]
elif n==(range(10,13)):
return [10]
For example, if n==12 I want it to return [10],and if n==5 I want it return [5]. I am getting no return back from the Python shell.
Let's consider this expression you wrote: n==(range(2,10))
n presumably is a single number - it cannot possibly be equal to a range of numbers!
However, you could write the test as n in range(2,10) and it would do what you want - although somewhat inefficiently, as it would actually be creating a list of numbers each time the test is performed, then searching linearly through that list. Using xrange instead of range would be more efficient, as it does not actually create the list.
Another way to do the same test would be 2 <= n < 10 (which is basically the same thing as (2 <= n) and (n < 10))

while executing loop the error is list indices must be intergers,not tuple

I want to store all the iteration output in a matrix(of size 200x200).
While executing the code : got the error at the
for t in (T2/Taw)*np.arange(-Taw,Taw-1):
i=i+1;
j=0;
for Fd in (B/Taw)*np.arange(-Taw,Taw-1):
j=j+1;
val1=1-abs(t)/T2;
val2=pi*T2*val1;
val3=Fd+mu*t+np.spacing(1);
val4=val2*val3;
ambg[j,i]=np.abs(val1*(sin(val4)/(val4)))**2;
---> 62 ambg[j,i]=np.abs(val1*(sin(val4)/(val4)))**2;
TypeError: list indices must be integers, not tuple
ambg=[] is a list. It can only be indexed with an integer, e.g ambg[i]. ambg[i,j] is the equivalent to ambg[(i,j)], where (i,j) is a tuple. Hence the error message.
If ambg was a list of lists, then it could indexed as ambg[i],[j]. But lists of lists are often constructed by iteratively appending values to a list(s).
If you initialized ambg=np.zeros((N,M)) where i and j will range over range(N) and range(M), then your code should work.
However initializing a numpy array element by element like this is slow, and considered poor practice. I haven't studied your code in detail, but it looks like you might be able to construct ambg with vector operations using T = (T2/Taw)*np.arange(-Taw,Taw-1) and FD = (B/Taw)*np.arange(-Taw,Taw-1).
For example T[:,None] is a single column array, and FD[None,:] a
single row array, that together can be used to calculate the NxN array based on all combinations of their values.
Experiment with something simpler like I = np.arange(10) and J = np.arange(10), and look at I[:,None]*J[None,:], or their sum, or difference, etc.

Updating range() function in for loop

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.