In Java, we can do something like:
int i = 0;
while (i < 10)
System.out.println(i++);
where it iterates i and prints it. Can the same be done in python?
EDIT:
Specifically, I'd like to do something like:
words = ["red","green","blue"]
current_state = 0
for word in words:
for char in word:
print(char,current_state,current_state+1)
Result
r 0 1
e 1 2
d 2 3
g 3 4
r 4 5
e 5 6
....
If you want the equivalent of the ++ operator in Java, the answer is no. Python requires you to do:
i += 1
on its own line.
However, you may be looking for enumerate, which allows you to keep track of what index you are at while iterating over a container:
>>> for i, j in enumerate(['a', 'b', 'c', 'd']):
... print(i, j)
...
0 a
1 b
2 c
3 d
>>>
i = 0
while i < 10:
i += 1
print i
Related
I’m new to python coding and i dont understand why the nested for loop is only returning 0 1 2 for the firs Iteration.
Input:
x = 3
for i in range (x):
for j in range (x):
x = 2
print (i, '',j)
Output:
0 0
0 1
0 2
1 0
1 1
2 0
2 1
x is changed after it's passed to range to make range(3). You only see the effects of the change (i.e. range(2)) on the next loop.
The Concept behind Nested for Loops:
Let us break this problem down (I am a beginner myself!)
x = 3
for i in range (x):
Now the range function has 3 parts (start, stop, step)
start: start from this number
stop: maximum value
step: increments by this value
when we say range(x); it assumes x=3 as the stop/max value of range. The start value is by default taken as 0, and the step value is by default taken as 1. So the range we get here is [0,1,2,3) {starts from 0 and stops at 3}
So the values that 'i' can take are 0,1,and 2 because 3 is max of the range; it is not included in the values i and j can take.
So output until this point:
for i in range (x):
for j in range (x):
(printing i and j separated by a whitespace)is:
0 0
0 1
0 2
0 is printed at the start and the loop is iterated 2 more times.
(you are getting all zeroes printed first for i as the statement you have written sends an instruction to print all the values of j for one value in the outer/main for loop; because loop for j is nested inside the loop for i)
Now, x= 2 means that from this point, values 'j' can take are 0,1. Hence the second part of the output:
1 0
1 1
Similarly, the the third part of the output is:
2 0
2 1
Hence the final output you get is:
0 0
0 1
0 2
1 0
1 1
2 0
2 1
Long version
In the for statement "for target in expression :" the second part is an iterable object.
range is not a 'reserved' word; it is the name of a built-in type(class) witch is iterable
Note : The syntax highlighter cheats if it highlights range as a reserved word. It does this, because this is generally useful as range is mainly used in association with for. But this does not change what range is. However, this can mislead you.
As a result of the above:
the correct typing is range(x) not range (x)
range(x) build an objet of type range and initialize it with x.
Short answer
x is interpreted when it is passed to range().
Code to print the range objects:
x = 3
range_i = range(x)
print(f"i loop x: {x}, range(x):{range_i}")
for i in range_i:
range_j = range(x)
print(f"j loop x: {x}, range(x):{range_j}")
for j in range_j:
x = 2
print(i, ' ',j)
Output
i loop x: 3, range(x):range(0, 3)
j loop x: 3, range(x):range(0, 3)
0 0
0 1
0 2
j loop x: 2, range(x):range(0, 2)
1 0
1 1
j loop x: 2, range(x):range(0, 2)
2 0
2 1
Rule of thumb
Unless you really know what you are doing, do not mess with the expression of the for statement.
lst = ['a', 'b', 'c', 'd']
for x in lst:
if x == 'b':
lst.remove('a')
print(x, end = ' ')
gives
a b d
And
lst = ['a', 'b', 'c', 'd']
for x in lst:
if x == 'd':
lst.insert(0, 'z')
print(x, end = ' ')
does not end and 'z' never appears:
a b c d d d d d d d d d d d d d ...
Musing around
Note : what follows is NOT recommended
You can redefine range. (The example below is a very simplified redefinition: it does not take in account the second version of range : range(start, stop[, step]) neither it cares for other range specifications)
def range(n):
i = 0
while i <= n: # note the use of '<=' instead of '<'
yield i
i += 1
And now 'range' does not behave as it should.
Example:
for i in range(3):
print(x, end = ' ')
gives:
0 1 2 3
Yes: 0..3 not 0..2 as the 'true' range.
Basically, I need a code that takes an integer and then prints out the string of numbers with the certain range.
For example:
n = 11
1 2 2 3 3 3 4 4 4 4
n = 7
1 2 2 3 3 3 4
a = []
n = int(input())
if n == 0:
print(n)
for i in range(int(n) + 1):
a += [i] * i
a = ' '.join(map(str, a))
print(a[:n])
This does the job but it counts spaces as characters, so I tried to convert it to an int
n = int(n)
print(' '.join(a[:n]))
But when the n >= 47, it starts to print out 10 as 1 0 which is incorrect
I also tried this code
n = int(input())
for i in range(n):
b = (str(i) * i)
print(b, end = ' ')
But I don't understand how to separate the b with spaces without converting the string to a list and printing it in one line either.
I am not sure if it is even possible.
Maybe something like this?
# initialize variables:
number = 11
counter = 0
for i in range(number):
for j in range(i):
# print number:
print('%d ' %i, end='')
# increment counter (tracks how many numbres to print):
counter += 1
# exit inner loop if counter reaches number:
if counter >= number-1: break
# exit outer loop if counter reaches number:
if counter >= number-1: break
Output:
1 2 2 3 3 3 4 4 4 4
Here's a solution using itertools. Generators, chain, repeat and islice are all lazily evaluated, so this uses O(1) space.
>>> n = 7
>>> from itertools import chain, repeat, islice
>>> gen = chain.from_iterable(repeat(i, i) for i in range(1, n+1))
>>> for i in islice(gen, n):
... print(i, end=' ')
...
1 2 2 3 3 3 4
This seems simple. But this does solve the problem?
>>> for i in t:
... if i!=" ": print i
...
1
2
2
3
3
3
4
4
4
4
or even string replace like,
print t.replace(" ","\n")
1
2
2
3
3
3
4
4
4
4
This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 5 years ago.
Suppose I do the following:
>>> l = [[]]*2
>>> l
[[], []]
>>> l[0].append(1)
>>> l
[[1], [1]]
Why does 1 get appended to both lists?
[[]]*2 is a list of two references to the same list. You are appending to it and then seeing it twice.
Because there is really only one list. Consider this:
>>> l = [[]]
>>> l2 = l*2
>>> l2[0] is l[0]
True
>>> l2[1] is l[0]
True
*2 performed on a list does not copy the list but return a list of length 2 filled with the same reference.
What you probably wanted was this:
>>> l = [[] for _ in xrange(2)]
As #Asterisk mentions in a comment, the same behaviour is exposed by all common collections. As a rule of thumb it is therefore best to only use multiplication on immutable types with value-semantics.
Showcasing the difference with memory layout:
listOfLists = [[]] * 3
listOfListsRange = [[] for i in range(0, 3)]
Here's how i initialize a list of lists. Rows vary slowest.
nrows = 3; ncols = 5
l_of_ls = [[0]*ncols for i in range(nrows )]
for rix, r in enumerate(l_of_ls):
for cix, c in enumerate(r):
print rix, cix, 'val = ',c
RESULT
0 0 val = 0
0 1 val = 0
0 2 val = 0
0 3 val = 0
0 4 val = 0
1 0 val = 0
1 1 val = 0
1 2 val = 0
1 3 val = 0
1 4 val = 0
2 0 val = 0
2 1 val = 0
2 2 val = 0
2 3 val = 0
2 4 val = 0
Also Worth Noting for Indexing Purposes
for rix in range(nrows):
for cix in range(ncols):
print l_of_ls[rix][cix],
print
RESULT
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
I want to retain previous element in a for loop. Suppose I have a following loop
for i in range(5):
print i
0
1
2
3
4
I want to retain i=0 when i=1(previous value) in some variable. likewise i=2 when i=3 and so on. So,that I can use this previous value in a loop.
Put an initial value at the beginning, and then just reassign it at the end:
j = None
for i in range(5):
print "j:", j
print "i:", i
j = i
print
Output:
j: None
i: 0
j: 0
i: 1
j: 1
i: 2
j: 2
i: 3
j: 3
i: 4
Try this:
for i in range(5):
print i
if i > 0: print 'previous:\t%d' %(i-1)
It's not clear how you are planning on using the previous value but Python's itertools module recipe pairwise may work for you:
from itertools import tee, chain
def pairwise(iterable):
a, b = tee(iterable)
next(b, None)
return zip(a, b)
>>> for prev, curr in pairwise(range(5)):
... print(prev ,curr)
0 1
1 2
2 3
3 4
And you need curr to include 0:
>>> for prev, curr in pairwise(chain([None],range(5))):
... print(prev ,curr)
None 0
0 1
1 2
2 3
3 4
This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 5 years ago.
Suppose I do the following:
>>> l = [[]]*2
>>> l
[[], []]
>>> l[0].append(1)
>>> l
[[1], [1]]
Why does 1 get appended to both lists?
[[]]*2 is a list of two references to the same list. You are appending to it and then seeing it twice.
Because there is really only one list. Consider this:
>>> l = [[]]
>>> l2 = l*2
>>> l2[0] is l[0]
True
>>> l2[1] is l[0]
True
*2 performed on a list does not copy the list but return a list of length 2 filled with the same reference.
What you probably wanted was this:
>>> l = [[] for _ in xrange(2)]
As #Asterisk mentions in a comment, the same behaviour is exposed by all common collections. As a rule of thumb it is therefore best to only use multiplication on immutable types with value-semantics.
Showcasing the difference with memory layout:
listOfLists = [[]] * 3
listOfListsRange = [[] for i in range(0, 3)]
Here's how i initialize a list of lists. Rows vary slowest.
nrows = 3; ncols = 5
l_of_ls = [[0]*ncols for i in range(nrows )]
for rix, r in enumerate(l_of_ls):
for cix, c in enumerate(r):
print rix, cix, 'val = ',c
RESULT
0 0 val = 0
0 1 val = 0
0 2 val = 0
0 3 val = 0
0 4 val = 0
1 0 val = 0
1 1 val = 0
1 2 val = 0
1 3 val = 0
1 4 val = 0
2 0 val = 0
2 1 val = 0
2 2 val = 0
2 3 val = 0
2 4 val = 0
Also Worth Noting for Indexing Purposes
for rix in range(nrows):
for cix in range(ncols):
print l_of_ls[rix][cix],
print
RESULT
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0