Pax
Given a list of items:
```python
>>> givenList = [1, 2, 3]
```
I would like to convert the list to a list of tuples; where each tuple is a duplicate of every item in the list:
```python
>>> givenListOfTuples = [(1,1), (2,2), (3,3)]
```
## Current Solution
```python
givenList = [1, 2, 3]
givenListOfTuples = [(item, item) for item in givenList]
```
Given that `item` is repeated multiple times, intuition tells me that this may not be the most pythonic way to do this.
Is there an alternative solution?
Top Answer
wizzwizz4
I think you've probably found the most Pythonic solution already, but it depends on the context. In certain scenarios, this might be better:
```python
given_list = [1, 2, 3]
given_list_of_tuples = [(item,)*2 for item in given_list]
```
This has a slightly different _meaning_, even though it does the same thing. If it didn't occur to you, though, you probably don't want it; I can't think of a place I'd use it.
Your solution satisfies many of the lines of the Zen of Python:
> ```python
> >>> import this
> ```
>
> ## The Zen of Python, by Tim Peters
> Beautiful is better than ugly.
> **Explicit is better than implicit.**
> **Simple is better than complex.**
> Complex is better than complicated.
> **Flat is better than nested.**
> **Sparse is better than dense.**
> **Readability counts.**
> Special cases aren't special enough to break the rules.
> **Although practicality beats purity.**
> Errors should never pass silently.
> Unless explicitly silenced.
> In the face of ambiguity, refuse the temptation to guess.
> **There should be one-- and preferably only one --obvious way to do it.**
> Although that way may not be obvious at first unless you're Dutch.
> Now is better than never.
> Although never is often better than *right* now.
> If the implementation is hard to explain, it's a bad idea.
> **If the implementation is easy to explain, it may be a good idea.**
> Namespaces are one honking great idea -- let's do more of those!
If you look at the dissassembly, your solution is also close to optimal:
```python
>>> import dis
>>> dis.dis("[(item, item) for item in givenList]")
Disassembly of <code object <listcomp> at 0x7f66e13455d0, file "<dis>", line 1>:
1 0 BUILD_LIST 0
2 LOAD_FAST 0 (.0)
>> 4 FOR_ITER 12 (to 18)
6 STORE_FAST 1 (item)
8 LOAD_FAST 1 (item)
10 LOAD_FAST 1 (item)
12 BUILD_TUPLE 2
14 LIST_APPEND 2
16 JUMP_ABSOLUTE 4
>> 18 RETURN_VALUE
```
Compare with my solution:
```python
>>> dis.dis("[(item,)*2 for item in given_list]")
Disassembly of <code object <listcomp> at 0x7f66e13455d0, file "<dis>", line 1>:
1 0 BUILD_LIST 0
2 LOAD_FAST 0 (.0)
>> 4 FOR_ITER 14 (to 20)
6 STORE_FAST 1 (item)
8 LOAD_FAST 1 (item)
10 BUILD_TUPLE 1
12 LOAD_CONST 0 (2)
14 BINARY_MULTIPLY
16 LIST_APPEND 2
18 JUMP_ABSOLUTE 4
>> 20 RETURN_VALUE
```
And the (near) optimal:
```python
>>> dis.dis(hand_crafted_bytecode)
Dissassembly of <code object <listcomp> at 0x7f66e390f3a0, file "tapythonq1514.py", line 8>:
8 0 BUILD_LIST 0
9 2 LOAD_FAST 0 (.0)
10 >> 4 FOR_ITER 8 (to 14)
11 6 DUP_TOP
12 8 BUILD_TUPLE 2
13 10 LIST_APPEND 2
14 12 JUMP_ABSOLUTE 4
15 >> 14 RETURN_VALUE
```
A peephole optimiser would be able to transform your solution into this near-optimal bytecode, but not my solution. I think what you've got already is hard to beat.