Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Multiplex lists using zip
#1
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♣']
Reply
#2
No, in this case you would use itertools.product, as in print([str(value) + suit for value, suit in itertools.product(values, suits)]).
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#3
(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?
Reply
#4
Check out itertools in detail. It has a lot of good functions for looping. I also use combinations, chain, and cycle a lot.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#5
(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.
Reply
#6
(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?
Reply
#7
(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.
Reply
#8
(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.
Reply
#9
(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.
Reply
#10
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).
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Split dict of lists into smaller dicts of lists. pcs3rd 3 2,312 Sep-19-2020, 09:12 AM
Last Post: ibreeden
  sort lists of lists with multiple criteria: similar values need to be treated equal stillsen 2 3,190 Mar-20-2019, 08:01 PM
Last Post: stillsen

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020