Order of For Loops with Python List Comprehension - python

In this answer, it is claimed that
The best way to remember this is that the order of for loop inside the list comprehension is based on the order in which they appear in traditional loop approach. Outer most loop comes first, and then the inner loops subsequently.
However, this answer,, and my own experiment below, seem to show the opposite - i.e, the inner loop coming first.
In my example, I want j to represent the row number and i to represent the column number. I want 5 rows and 4 columns What am I missing please?
board = [[(j, i) for i in range(4)] for j in range(5)]
# I believe the above comprehension is equivalent to the nested for loops below
# board = []
# for j in range(5):
# new_row = []
# for i in range(4):
# new_row.append((j,i))
# board.append(new_row)
for j in range(5):
for i in range(4):
print(board[j][i], end="")
print()

This is the correct way to get desired output:
board = [(j, i) for i in range(4) for j in range(5)]
Output:-
[(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (0, 2), (1, 2), (2, 2), (3, 2), (4, 2), (0, 3), (1, 3), (2, 3), (3, 3), (4, 3)]

Related

Given a List get all the combinations of tuples without duplicated results

I have a list=[1,2,3,4]
And I only want to receive tuple results for like all the positions in a matrix, so it would be
(1,1),(1,2),(1,3),(1,4),(2,1),(2,2),(2,3),(2,4),(3,1),(3,2),(3,3),(3,4),(4,1),(4,2),(4,3),(4,4)
I've seen several codes that return all the combinations but i don't know how to restrict it only to the tuples or how to add the (1,1),(2,2),(3,3),(4,4)
Thank you in advance.
You just need a double loop. A generator makes it easy to use
lst = [1,2,3,4]
def matrix(lst):
for i in range(len(lst)):
for j in range(len(lst)):
yield lst[i], lst[j]
output = [t for t in matrix(lst)]
print(output)
Output:
[(1, 1), (1, 2), (1, 3), (1, 4), (2, 1), (2, 2), (2, 3), (2, 4), (3, 1), (3, 2), (3, 3), (3, 4), (4, 1), (4, 2), (4, 3), (4, 4)]
If you just want to do this for making pairs of all symbols in the list
tuple_pairs = [(r,c) for r in lst for c in lst]
If you have instead some maximum row/colum numbers max_row and max_col you could avoid making the lst=[1,2,3,4] and instead;
tuple_pairs = [(r,c) for r in range(1,max_row+1) for c in range(1,max_col+1)]
But that's assuming that the lst's goal was to be = range(1, some_num).
Use itertools.product to get all possible combinations of an iterable object. product is roughly equivalent to nested for-loops with depth specified by the keyword parameter repeat. It returns an iterator.
from itertools import product
lst = [1, 2, 3, 4]
combos = product(lst, repeat=2)
combos = list(combos) # cast to list
print(*combos, sep=' ')
Diagonal terms can be found in a single loop (without any extra imports)
repeat = 2
diagonal = [(i,)*repeat for i in lst]
print(*diagonal sep=' ')
You can do that using list comprehension.
lst=[1,2,3,4]
out=[(i,i) for i in lst]
print(out)
Output:
[(1, 1), (2, 2), (3, 3), (4, 4)]

Number of passengers. Error: list indices must be integers or slices, not list

So, I'm trying to sum the number of passenger at each stop.
The "stops" variable are the number of stops, and is conformed by a tuple which contains the in's and out's of passengers, example:
stops = [(in1, out1), (in2, out2), (in3, out3), (in4, out4)]
stops = [(10, 0), (4, 1), (3, 5), (3, 4), (5, 1), (1, 5), (5, 8), (4, 6), (2, 3)]
number_passenger_per_stop = []
for i in stops:
resta = stops[i][0] - stops[i][1]
number_passenger_per_stop.append(resta)
print(number_passenger_per_stop)
I can do the math like this outside the loop, but I don't understand why in the loop crashes:
stops[i][0] - stops[i][1]
i is not the list index, it's the list element itself. You don't need to write stops[i].
resta = i[0] - i[1]
Your code would be correct if you had written
for i in range(len(stops)):
You could also replace the entire thing with a list comprehension:
number_passenger_per_stop = [on - off for on, off in stops]
I just edited the for loop to adress each in the index in the list correctly, you needed to call each element in the list by its position, and not by its value:
stops = [(10, 0), (4, 1), (3, 5), (3, 4), (5, 1), (1, 5), (5, 8), (4, 6), (2, 3)]
number_passenger_per_stop = []
for i in range(len(stops)):
resta = stops[i][0] - stops[i][1]
number_passenger_per_stop.append(resta)
print(number_passenger_per_stop)
Output:
[10, 3, -2, -1, 4, -4, -3, -2, -1]

How to iterate over a dictionary of tuples

I have a list of tuples called possible_moves containing possible moves on a board in my game:
[(2, 1), (2, 2), (2, 3), (3, 1), (4, 5), (5, 2), (5, 3), (6, 0), (6, 2), (7, 1)]
Then, I have a dictionary that assigns a value to each cell on the game board:
{(0,0): 10000, (0,1): -3000, (0,2): 1000, (0,3): 800, etc.}
I want to iterate over all possible moves and find the move with the highest value.
my_value = 0
possible_moves = dict(possible_moves)
for move, value in moves_values:
if move in possible_moves and possible_moves[move] > my_value:
my_move = possible_moves[move]
my_value = value
return my_move
The problem is in the part for move, value, because it creates two integer indexes, but I want the index move to be a tuple.
IIUC, you don't even need the list of possible moves. The moves and their scores you care about are already contained in the dictionary.
>>> from operator import itemgetter
>>>
>>> scores = {(0,0): 10000, (0,1): -3000, (0,2): 1000, (0,3): 800}
>>> max_move, max_score = max(scores.items(), key=itemgetter(1))
>>>
>>> max_move
(0, 0)
>>> max_score
10000
edit: turns out I did not understand quite correctly. Assuming that the list of moves, let's call it possible_moves, contains the moves possible right now and that the dictionary scores contains the scores for all moves, even the impossible ones, you can issue:
max_score, max_move = max((scores[move], move) for move in possible_moves)
... or if you don't need the score:
max_move = max(possible_moves, key=scores.get)
You can use max with dict.get:
possible_moves = [(2, 1), (2, 2), (2, 3), (3, 1), (4, 5), (5, 2),
(5, 3), (6, 0), (6, 2), (7, 1), (0, 2), (0, 1)]
scores = {(0,0): 10000, (0,1): -3000, (0,2): 1000, (0,3): 800}
res = max(possible_moves, key=lambda x: scores.get(x, 0)) # (0, 2)
This assumes moves not found in your dictionary have a default score of 0. If you can guarantee that every move is included as a key in your scores dictionary, you can simplify somewhat:
res = max(possible_moves, key=scores.__getitem__)
Note the syntax [] is syntactic sugar for __getitem__: if the key isn't found you'll meet KeyError.
If d is a dict, iterator of d generates keys. d.items() generates key-value pairs. So:
for move, value in moves_values.items():
possibleMoves=[(2, 1), (2, 2), (2, 3), (3, 1), (4, 5), (5, 2),(0, 3),(5, 3), (6, 0), (6, 2), (7, 1),(0,2)]
movevalues={(0,0): 10000, (0,1): -3000, (0,2): 1000, (0,3): 800}
def func():
my_value=0
for i in range(len(possibleMoves)):
for k,v in movevalues.items():
if possibleMoves[i]==k and v>my_value:
my_value=v
return my_value
maxValue=func()
print(maxValue)

For loop to compare one element with all the remaining elements of an array

I have an array in Python [0,1,2,3,4] with 5 elements. I want to compare elements in following fashion.
(0,1),(0,2),(0,3),(0,4),(1,2),(1,3),(1,4),(2,3),(2,4),(3,4),(4,4)
What I am doing is as follows.
for i in range(len(array)):
for j in range(i+1,len(array)):
But this is comparing in following fashion.
(0,1),(1,2),(2,3),(3,4)...
Where I am doing it wrong?
This code produces the desired result:
array = [0,1,2,3,4]
for i in range(len(array)):
for j in range(i+1,len(array)):
print(array[i], array[j])
print(array[-1], array[-1])
This code is one way that you may have gotten the erroneous result:
for i in range(len(array)):
for j in range(i+1,len(array)):
print(array[i], array[j])
break
Using itertools is another option:
>>> [x for x in itertools.combinations(xrange(5), 2)]
[(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]

returning a list of tuples like zip, generate it incrementally a tuple at a time, using comprehensions

I need a function which returns a tuple one at a time from a list of sequences without using zip . i tried to do it in this fashion:
gen1=[(x,y)for x in range(3) for y in range(4)]
which gives the following list:
[(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3)]
next I tried to return one tuple at a time by:
next(gen1)
But an error occured that list is not 'iterable' . how can i do it using generators.
If you want the behavior to work with an arbitrary number of sequences, while there are still some ambiguities in the question, if what you're trying to do is just make a generator version of zip, the below should work well:
def generator_zip(*args):
iterators = map(iter, args)
while iterators:
yield tuple(map(next, iterators))
First it turns each arg into an iterator, then continues to yield tuple that include the next relevant entry from each iterator until the shortest list is exhausted.
As of Python 2.4, you can do:
gen1 = ((x, y) for x in range(3) for y in range(4))
Note that you can always make a generator (well, iterator) from a list with iter:
gen1 = iter([(x, y) for x in range(3) for y in range(4)])
The difference in usage will be none. The second way will require the whole list to be in memory, though, while the first will not.
Note that you can also use the builtin functionality of zip, which is a generator (in Python 3). In Python 2, use itertools.izip.
Python 3:
>>> zip(range(0, 5), range(3, 8))
<zip object at 0x7f07519b3b90>
>>> list(zip(range(0, 5), range(3, 8)))
[(0, 3), (1, 4), (2, 5), (3, 6), (4, 7)]
Python < 3:
# Python < 3
>>> from itertools import izip
>>> izip(range(0, 5), range(3, 8))
<itertools.izip object at 0x7f5247807440>
>>> list(izip(range(0, 5), range(3, 8)))
[(0, 3), (1, 4), (2, 5), (3, 6), (4, 7)]
>>> zip(range(0, 5), range(3, 8))
[(0, 3), (1, 4), (2, 5), (3, 6), (4, 7)]

Categories

Resources