What is the difference between len(x) and len(x)-1? [duplicate] - python

This question already has answers here:
Why does range(start, end) not include end? [duplicate]
(11 answers)
Closed 2 years ago.
I'm sorry for the very basic question, this is a concept I can't quite grasp.
It is my understanding that the first element in a Python list has index [0]. This means that len(x)-1 should be the last element in my list x.
So, if I write a loop with:
for i in range(0, len(x)-1):
#do stuff here
This should mean that I want I to go from the first element of my list to the last one.
However, I always find written:
for i in range(0, len(x)):
#do stuff here
Why is that?
Which one is correct?

range(0,x) will loop up to the value of x, so < x as opposed to <= x. For example, range(0, 3) will loop over the indices 0, 1, 2.
Which means the second one is correct, as if x = [4, 5, 6, 7] (len 4) - the maximum index is 3 so you'd want to loop over the indices 0, 1, 2, 3.

range(x, y) means to start with x and iterate till y-1 so when you use for i in range(0, len(x)-1):, it will iterate from 0 to len(x) - 2.
For example if, len(x) = 3, the statement for i in range(0, len(x)-1): will iterate from 0 to 1 so that's why we use for i in range(0, len(x)): to iterate over all the elements in the list.

Related

Is there a way to find the position of my for loop variable in a integer list [duplicate]

This question already has answers here:
Accessing the index in 'for' loops
(26 answers)
Closed 3 months ago.
For example, num = [4, 6, 2, 5, 7]
for i in num:
for j in num:
j = num[i+1]
Is there a way to find if i is in the 0 position, 1 position, 2 position, ...
so that I can make it were j = what position i is in +1
I also want to make it were if, lets say i was in position 1;
if i == i+1:
num.remove(i)
I already tried i+1 just doing i plus one and i could do a bunch of if statements and just make it do 1 over but i have like 4 variable for the for loop all in different position of i and I'm worried it will say list(x) out of index. I also tried .find put it didn't work for a list.
Also, I need to make it as too were it doesn’t change the original value of the integer so that I can add them up, would I have to make too lists.
Yes, what you're looking for is the enumerate function, which takes in a list and gives you both the index and the value of each element in the list:
nums = [4, 6, 2, 5, 7]
for index, value in enumerate(nums):
print(index, value)
# will print
# (0, 4)
# (1, 6)
# (2, 2)
# (3, 5)
# (4, 7)
Some extra info from RealPython: https://realpython.com/python-enumerate/

When i trying to remove elements in a list it is not working can anyone explain me why this is not working [duplicate]

This question already has answers here:
Strange result when removing item from a list while iterating over it
(8 answers)
Closed last year.
This is the code I have used and it is not removing last zero it is skipping
x = [1,2,3,0,0,0]
for I in x:
if I==0:
x.remove(I)
print(x)
output:
[1, 2, 3, 0]
so from the output the last zero is not removing why
Why don't you use this simple list comprehension.
x = [1,2,3,0,0,0]
y=[i for i in x if i != 0]
print(y)
You'll get a new list (y) with the 0 removed, while the x is preserved in it's original state.
[1, 2, 3]
Process finished with exit code 0
For more study on list.remove(), check this
List.remove() does not remove all occurrances
As per documentation, list.remove removes first element whose value matches given number.
So, when first '0' at index 3 is removed, the new list is [1,2,3,0,0] with the list iteration index at 4. The following 0 (which was at index 4 in original list) moves back one place and is getting skipped. This can be seen with following code:
x = [0,0,0,0,0,0]
for id, i in enumerate(x):
print(id, i)
if i == 0:
print(x, i)
x.remove(i)
print(x)
In this, every second element is missed, and final x is [0, 0, 0]
As for what is correct way to do this, list comprehension is a good way, as answered by Anand: x = [i for i in x if i!=0]

How do I derive this part of the algorithm

I'm a beginner at programming Python and came across this program.
This algorithm is used to reverse a list:
mylist = [1,2,3,4]
reverse = mylist[:]
for i in range(len(reverse)//2):
reverse[i], reverse[len(reverse) -i -1] = reverse[len(reverse) -i -1], reverse[i]
This algorithm is based on the logic that the swapping process will happen only till the len/2 element for lists with even lengths or the len/2 element in case of lists with a odd length because if the swapping process occurred till the last element, the list would remain the same as it was in the beginning.
I understood what the below part does, but how do I derive it, please explain the logic:
reverse[len(reverse) -i -1]
len(reverse) returns the number of elements the list has. To actually use it as an index you need to subtract 1 from it as indices start from 0. Next, we also subtract i from it as we are moving i positions away from both ends of the list and swapping them.
So if i=1 reverse[i] points to 2 while reverse[len(reverse)-i-1 points to 3.
You can just print the contents of these variables:
lst = [1, 2, 3, 4, 5, 6]
for i in range(len(lst)//2):
print(i, len(lst) - i - 1)
This will print
0 5
1 4
2 3
Therefore,
for the index of the first element (i = 0), len(lst) - i - 1 will return the index of the last element (i = 5).
for the index of the second element (i = 1), len(lst) - i - 1 will return the index of the second to last element (i = 4).
And so on.

How to update loop variable with range function? [duplicate]

This question already has answers here:
How to remove items from a list while iterating?
(25 answers)
Closed 2 years ago.
I want to remove duplicates from a list. I know it can be done easily with list(dict.fromkeys(my list)), but I want to do it by iterating through the list. When I am removing a duplicate number from the list, the loop variable j causes an Index error : list index out of range later in subsequent iterations, even though I am changing the range input. I am wondering how to change loop variable inside loop ?
def rem_duplicate(seq):
for i in range(len(seq)):
num = seq[i]
count = 0
length = len(seq)
for j in range(length):
if seq[j] == num:
count += 1
if count > 1:
del seq[j]
length=length-1
return seq
my_list = [2, 3, 4, 5, 6, 7, 8, 3, 4, 1, 5, 2, 5, 7, 9]
print(rem_duplicate(my_list))
When you enter the inner loop, the range() function is called with current value of length, say, 3. So, your loop would look like for j in [1, 2, 3] and changing length won't affect changing the mentioned list.
To achieve what you want, and also when mutating the size of the list you're iterating on, it's always better to use a while loop:
j = 0
while j < length:
if seq[j] == num:
count += 1
if count > 1:
del seq[j]
length=length-1
j += 1
range(len(seq))
Will return an inmutable sequence, that will not be affected by add / del operations over the original list.
Take a look to the previous answers to the same question (using a while): Python: remove duplicate items from a list while iterating

is there a major difference between using a range of range (i[0], len(i) and [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am brand new to python. I have been learning this on my own. I always make sure to exhaust every resource before asking a question on here.
but I will show you two sets of code. One does what I want, the other doesn't the only difference that appears to me, is how the ranges are set up. I don't understand the significance of this difference. Could someone please explain?
Thank you.
Code that works
def geometric(lst):
'checks whether the integers in list lst form a geometric sequence'
if len(lst) <= 1:
return True
ratio = lst[1]/lst[0]
for i in range(1, len(lst)-1):
if lst[i+1]/lst[i] != ratio:
return False
return True
**code that doesn't **
def geometric(integerList):
'checks whether the integers in list lst form a geometric sequence'
if len(lst) <= 1:
return True
ratio = integerList[1]/integerList[0]
for i in range (integerList[0], len(integerList))
if lst[i+1]/lst[i] != ratio:
return False
return True
In the first case, range(1, len(lst)-1) is a list
1, 2, 3, ..., len(lst)-1
In the second case, it depends on the value of the first list element. If integerList[0] is 3, then range() is
3, 4, 5, ..., len(lst)-1
and the first call of the if() statement compares integerList[4] / integerList[3] and ignores the first three elements in the list. So, the code only works, if integerList[0] == 1
However, there are two further pitfalls:
range() only takes integers as elements. If the first element is a float, pyhon will throw an error.
If the ratio always is an integer, you can compare the ratios for equality, as you do. But if ratio is a floating value, you can get into trouble: Though two ratios are mathematically equal, a computer (due to its floating point arithmetic) may calculate slightly different values. It is better to use
import math
...
if (math.fabs(lst[i+1]/lst[i] - ratio) < smallNumber)
where smallNumer is a very small number suitable for you.
By the way: In your second code, you use lst[] , but I guess, it was just a typo.
As Noelkd said, the range in your second code block starts with the value of the first element of the list, not its position.
If my list is the geometric sequence (1, 2, 4, 8, 16), your first block's range is
range(1, len(lst)-1) =
range(1, 5 - 1) =
range(1, 4) =
[1, 2, 3]
and your second block's range is
range(integerList[0], len(integerList)) =
range(1, 5) =
[1, 2, 3, 4]
This difference gets even weirder if my sequence doesn't start with 1, such as for the sequence (3, 9, 27):
First block's range is
range(1, len(lst)-1) =
range(1, 3 - 1) =
range(1, 2) =
[1]
and second block's range is
range(integerList[0], len(integerList)) =
range(3, 3) =
[]
for i in range(1, len(lst)-1):
...
This code first creates a list containing the numbers [1,2,3,...,len(lst)-1] and then loops over these values by setting i to a value in this list on every iteration.
for i in range (integerList[0], len(integerList))
This code actually creates a list containing the numbers:
[integerList[0],integerList[0] + 1,integerList[0] + 2,...,len(integerList)]
Here you're starting the range at integerList[0] not it's index. And if integerList[0] is bigger than len(integerList) you'll get an array with no values []
You also then try to use lst in the second function when really you're looking for integerList
This should help you understand what's happening:
>>> x = [2,4,5,6,7,8]
>>> for i in range(1,len(x)):
... print x[i]
...
4
5
6
7
8
So that's printing from the second to the last item.
>>> for i in range(x[0],len(x)):
... print x[i]
...
5
6
7
8
The second block is starting from x[0] which is 2 so from the third element to the last element.
Unless integerList[0] is always equal to 1 then you will not get the same range as range(1, len(lst)-1) which starts at 1, if integerList[0] == 5 your range will be range(5, len(integerList)) so you would miss elements from indexes 1 - 4 that you get in your first block of code and it would also throw an index error as lst[i+1] would be 1 index past the end of the list:
It would also be better to use enumerate:
def geometric(lst):
'checks whether the integers in list lst form a geometric sequence'
if len(lst) <= 1:
return True
ratio = lst[1] / lst[0]
for ind, ele in enumerate(lst[1:-1]):
if lst[ind+1] / ele != ratio:
return False
return True
In [4]: lst = ["foo","bar","foobar"]
In [5]: for ind, ele in enumerate(lst):
...: print ind,ele
...:
0 foo
1 bar
2 foobar

Categories

Resources