Posts: 158
Threads: 27
Joined: Jan 2019
This is just a curiosity. Is there a way to use zip to replace the list comprehension in this code?
values = list(range(2,11)) + ['J', 'Q', 'K', 'A']
suits = ['♠', '♦', '♥', '♣']
print([str(value) + suit for value in values for suit in suits]) Output: ['2♠', '2♦', '2♥', '2♣', '3♠', '3♦', '3♥', '3♣', '4♠', '4♦', '4♥', '4♣', '5♠', '5♦', '5♥', '5♣', '6♠', '6♦', '6♥', '6♣', '7♠', '7♦', '7♥', '7♣', '8♠', '8♦', '8♥', '8♣', '9♠', '9♦', '9♥', '9♣', '10♠', '10♦', '10♥', '10♣', 'J♠', 'J♦', 'J♥', 'J♣', 'Q♠', 'Q♦', 'Q♥', 'Q♣', 'K♠', 'K♦', 'K♥', 'K♣', 'A♠', 'A♦', 'A♥', 'A♣']
Posts: 4,220
Threads: 97
Joined: Sep 2016
No, in this case you would use itertools.product, as in print([str(value) + suit for value, suit in itertools.product(values, suits)]) .
Posts: 158
Threads: 27
Joined: Jan 2019
Dec-02-2019, 04:07 PM
(This post was last modified: Dec-02-2019, 04:27 PM by Clunk_Head.)
(Dec-02-2019, 03:42 PM)ichabod801 Wrote: No, in this case you would use itertools.product, as in print([str(value) + suit for value, suit in itertools.product(values, suits)]) .
It can be made even simpler:
[f'{v}{s}' for v,s in itertools.product(values, suits)] but is there a way to do it without creating an iterable and then iterating though it to create the string?
Posts: 4,220
Threads: 97
Joined: Sep 2016
Check out itertools in detail. It has a lot of good functions for looping. I also use combinations, chain, and cycle a lot.
Posts: 158
Threads: 27
Joined: Jan 2019
(Dec-02-2019, 04:26 PM)ichabod801 Wrote: Check out itertools in detail. It has a lot of good functions for looping. I also use combinations, chain, and cycle a lot.
Sounds good.
The current solution is O(2*(m*n)), it would be great to get it to O(m*n) like the original list comprehension.
Posts: 360
Threads: 5
Joined: Jun 2019
Dec-02-2019, 04:34 PM
(This post was last modified: Dec-02-2019, 04:37 PM by ThomasL.)
(Dec-02-2019, 04:29 PM)Clunk_Head Wrote: The current solution is O(2*(m*n)), it would be great to get it to O(m*n) like the original list comprehension. Why do you think it is O(2*(m*n)) ? Please explain.
(Dec-02-2019, 04:07 PM)Clunk_Head Wrote: but is there a way to do it without creating an iterable and then iterating though it to create the string? How do you think this could be possible?
In your first code example you are creating two iterables called values and suits.
How do you want to do what you want to do without these?
Posts: 158
Threads: 27
Joined: Jan 2019
(Dec-02-2019, 04:34 PM)ThomasL Wrote: Why do you think it is O(2*(m*n)) ? Please explain. itertools.product(values, suits) must traverse values (len m) and for each must traverse suits (len n) to create the iterable that is returned. Then the iterable (len m*n) is traversed again by the list comprenesion. This makes the complexity double the length of the combined list, or 2*m*n
(Dec-02-2019, 04:34 PM)ThomasL Wrote: (Dec-02-2019, 04:07 PM)Clunk_Head Wrote: but is there a way to do it without creating an iterable and then iterating though it to create the string? How do you think this could be possible?
In your first code example you are creating two iterables called values and suits.
How do you want to do what you want to do without these? That's why I'm asking, but I think you've missed the point of the question. I am asking how to combine the to iterables together into a list of strings exactly as the first list comprehension does, but using a single function call. I am not looking to skip the creation of the initial iterables as that is not being counted in the complexity.
Posts: 360
Threads: 5
Joined: Jun 2019
(Dec-02-2019, 05:16 PM)Clunk_Head Wrote: itertools.product(values, suits) must traverse values (len m) and for each must traverse suits (len n) to create the iterable that is returned. Then the iterable (len m*n) is traversed again by the list comprenesion. This makes the complexity double the length of the combined list, or 2*m*n If we look here we see some code but read that "This function is roughly equivalent to the following code, except that the actual implementation does not build up intermediate results in memory"
which means that it is not as you described it to be.
Posts: 158
Threads: 27
Joined: Jan 2019
(Dec-02-2019, 05:33 PM)ThomasL Wrote: (Dec-02-2019, 05:16 PM)Clunk_Head Wrote: itertools.product(values, suits) must traverse values (len m) and for each must traverse suits (len n) to create the iterable that is returned. Then the iterable (len m*n) is traversed again by the list comprenesion. This makes the complexity double the length of the combined list, or 2*m*n If we look here we see some code but read that "This function is roughly equivalent to the following code, except that the actual implementation does not build up intermediate results in memory"
which means that it is not as you described it to be.
itertools.product(values, suits) produces:
Output: [('2', '♠'), ('2', '♦'), ('2', '♥'), ('2', '♣'), ('3', '♠'), ('3', '♦'), ('3', '♥'), ('3', '♣'), ('4', '♠'), ('4', '♦'), ('4', '♥'), ('4', '♣'), ('5', '♠'), ('5', '♦'), ('5', '♥'), ('5', '♣'), ('6', '♠'), ('6', '♦'), ('6', '♥'), ('6', '♣'), ('7', '♠'), ('7', '♦'), ('7', '♥'), ('7', '♣'), ('8', '♠'), ('8', '♦'), ('8', '♥'), ('8', '♣'), ('9', '♠'), ('9', '♦'), ('9', '♥'), ('9', '♣'), ('1', '♠'), ('1', '♦'), ('1', '♥'), ('1', '♣'), ('0', '♠'), ('0', '♦'), ('0', '♥'), ('0', '♣'), ('J', '♠'), ('J', '♦'), ('J', '♥'), ('J', '♣'), ('Q', '♠'), ('Q', '♦'), ('Q', '♥'), ('Q', '♣'), ('K', '♠'), ('K', '♦'), ('K', '♥'), ('K', '♣'), ('A', '♠'), ('A', '♦'), ('A', '♥'), ('A', '♣')]
Which is O(m*n), as I described it and the documentation that you provided specifies.
My target output is:
Output: ['2♠', '2♦', '2♥', '2♣', '3♠', '3♦', '3♥', '3♣', '4♠', '4♦', '4♥', '4♣', '5♠', '5♦', '5♥', '5♣', '6♠', '6♦', '6♥', '6♣', '7♠', '7♦', '7♥', '7♣', '8♠', '8♦', '8♥', '8♣', '9♠', '9♦', '9♥', '9♣', '10♠', '10♦', '10♥', '10♣', 'J♠', 'J♦', 'J♥', 'J♣', 'Q♠', 'Q♦', 'Q♥', 'Q♣', 'K♠', 'K♦', 'K♥', 'K♣', 'A♠', 'A♦', 'A♥', 'A♣']
Which requires another pass, that is what doubles the number of steps to O(2*m*n)
[f'{v}{s}' for v,s in itertools.product(values, suits)] My follow-up question is whether it's possible to specify that itertools.product or some other function can return the 2nd output without the intermediate step.
Posts: 4,220
Threads: 97
Joined: Sep 2016
No, it's all in the same pass. That's what ThomasL (quoting the documentation) was saying. Product creates the first tuple, and then passes that out to the list comprehension, which then creates the first string. Only then does product create the second tuple, and again that is returned/yielded and processed into a string before the third tuple is generated. So you are only passing through once, for O(n * m).
|