3

Is there a way to copy an array.array (not a list) in Python, besides just creating a new one and copying values, or using .to_something and .from_something? I can't seem to find anything in the documentation. If not, is there a similar builtin datatype that can do this?

I am working on a high-performance module, so the faster the answer, the better.

My current solution is just using .to_bytes and .from_bytes, which is about 1.8 times faster from my tests.

internet_user
  • 3,149
  • 1
  • 20
  • 29

3 Answers3

5

Not sure what your array.array includes, but using a sample:

>>> import array
>>> a = array.array('i', [1, 2, 3] * 1000)
array('i', [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1,
2, 3, 1, 2, 3, 1, 2, 3, 1, 2, ... ])

Some set up:

>>> from copy import deepcopy
>>> import numpy as np

Timing various methods

(using the %timeit magic in a Jupyter Notebook):

Slicing

In [1]: %timeit cp = a[:]

418 ns ± 4.89 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Deepcopy

In [2]: %timeit cp = deepcopy(a)

1.83 µs ± 34 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

numpy copy ... NOTE: This produces a numpy array, not an array.array

In [3]: %timeit cp = np.copy(a)

1.87 µs ± 62.4 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

List Comprehension and array.array conversion

In [4]: %timeit cp = array.array('i', [item for item in a])

147 µs ± 5.39 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

numpy copy and array.array conversion

In [5]: %timeit cp = array.array('i', np.copy(a))

310 µs ± 2.25 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Copying to an existing array

In[6]: pre = array.array('i', [0, 0, 0] * 1000)
In[7]: %timeit for i, element in enumerate(a): pre[i] = a[i]

344 µs ± 7.83 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
E. Ducateme
  • 4,028
  • 2
  • 20
  • 30
  • 1
    The one I mentioned I found to be faster is `a * 1`. I suspect under the hood it's equivalent to `a[:]` but it gets under the hood more quickly (as in, it reaches the copying code more quickly: https://ideone.com/KLb3wl). Only noticeable with small arrays, though. – Stefan Pochmann Jan 05 '18 at 16:32
  • If I'm not wrong, `array.array` can't store mutable items. So there's no point in using `copy.deepcopy` instead of `copy.copy`. – nog642 Jan 05 '18 at 17:12
1

You don't need numpy to copy an array.array object. And since array.array objects can only contain ints, floats, or unicode characters, the concept of "shallow copy" and "deep copy" don't apply here.

You can just use the [:] trick to make a copy of an array.array() object:

>>> import array
>>> x = array.array('B', b'\xFF' * 10)
>>> x
array('B', [255, 255, 255, 255, 255, 255, 255, 255, 255, 255])
>>> y = x[:]
>>> y
array('B', [255, 255, 255, 255, 255, 255, 255, 255, 255, 255])

You can also pass it to the array.array() initializer function.

For example:

>>> import array
>>> x = array.array('B', b'\xFF' * 10)
>>> x
array('B', [255, 255, 255, 255, 255, 255, 255, 255, 255, 255])
>>> y = array.array('B', x)
>>> y
array('B', [255, 255, 255, 255, 255, 255, 255, 255, 255, 255])

Be sure to pass the same "type code" (the 'B' in the above example) for the new array.array object.

Al Sweigart
  • 11,566
  • 10
  • 64
  • 92
0

copy.copy(arr) would work fine.

nog642
  • 569
  • 3
  • 15
  • This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post. - [From Review](/review/low-quality-posts/18429898) – 31piy Jan 05 '18 at 04:44
  • 3
    @31piy How exactly does it not answer the question? Rather looks like you didn't read the question. And how does this "critique or request clarification"? – Stefan Pochmann Jan 05 '18 at 16:48