1

if I have this Python array:

mac_tags = [ "global_rtgn", "global_mogn" ]

And I want this Python array:

mac_tags = [ "global_rtgn", "global_rtgn", "global_mogn","global_mogn" ]

How might I create it programmatically?

Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
Terrence Brannon
  • 4,760
  • 7
  • 42
  • 61

4 Answers4

4
new_mac_tags = []
for tag in mac_tags:
    new_mac_tags += [tag, tag]

or

from itertools import chain, izip
new_mac_tags = list(chain.from_iterable(izip(mac_tags, mac_tags)))
Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
1
>>> [a for a in mac_tags for x in range(2)]
['global_rtgn', 'global_rtgn', 'global_mogn', 'global_mogn']
Dzinx
  • 55,586
  • 10
  • 60
  • 78
-1
[i for i in sorted(mac_tags+mac_tags)]
user1016274
  • 4,071
  • 1
  • 23
  • 19
-1

Please note that this is more of a functional way of doing this and may not be pure idiomatic python code.

data = [[s, s] for s in [ "global_rtgn", "global_mogn" ]]

data = sum (data, [])

print data
RStrad
  • 152
  • 7
  • (a) This seems like an abuse of `sum` (b) by using sum, you lose the ability to use zip/izip instead of writing your own. – Marcin Mar 06 '12 at 16:28
  • @Marcin: The worst problem with this approach is that it is O(n^2). – Sven Marnach Mar 06 '12 at 16:34
  • @SvenMarnach: How so? Surely one traversal for the zipping, plus one traversal for the sum. Or do you mean that memory allocation will be O(n^2)? Is CPython unable to optimise this? – Marcin Mar 06 '12 at 16:38
  • @Marcin: The `+` operator on lists creates a new list. Using `sum()` here creates a new list in every iteration, copying everything that has been accumulated so far. It would be possible to optimise this, but it isn't trivial to do, and CPython doesn't. This use of `sum()` is considered wrong, so no efforts will be made to optimise it. Using a list comprehension with two `for` clauses or `itertools.chain.from_iterable()` are considered the right ways. In fact, it is more likely that future Python version reject this use of `sum()` (as they already to for strings) than that it gets optimised. – Sven Marnach Mar 06 '12 at 16:44
  • @SvenMarnach: I understand the python-level semantics of `+`, but there is still no reason why it *has* to copy every time, rather than optimising the concatenation. – Marcin Mar 06 '12 at 16:54
  • @Marcin: It has to copy in the first step, since it is not allowed to modify the object passed in as the `start` parameter. And the implementation basically invokes the `__add__()` method of whatever objects it gets. Optimising this for lists would need some special-casing in the implementation of `sum()`. – Sven Marnach Mar 06 '12 at 16:56
  • @SvenMarnach No, it wouldn't require any special casing in `sum`. All it would require is for `__add__` to be optimised where the left operand has no references to it outside of the calling context and the next thing that is going to happen to it is that it is going to be the left operand of another `__add__` call. In that case, an optimising compiler could simply extend the array backing the left operand, and copy the contents of the right operand into the new space. It's not an insanely complex optimisation. – Marcin Mar 06 '12 at 17:14
  • @Marcin: No, it wouldn't be as easy as this because it would change the C interface in an incompatible way. A reference count of 1 means there are no further Python references, but a calling C function could still very well hold an external reference -- [I discussed exactly this before](http://stackoverflow.com/a/7895490/279627). This means the optimisation would have to be done in `sum()`, and it would need to special-case lists. – Sven Marnach Mar 06 '12 at 17:38
  • @SvenMarnach Yes, obviously I am talking about a change to the way the python interpreter itself works. You only need a specific optimisation in `sum` if you assume *no other changes whatsoever to any code*. – Marcin Mar 06 '12 at 17:42