2

Is there a way to obtain the same result from this Python-arrays merge:

a = [1,2,3,4]

b = [4,3,2,1]

c = [ int(''.join (map (str, xs))) for xs in zip (a,b) ]

c
Out[4]: [14, 23, 32, 41]

But operating directly on Numpy-arrays:

a
Out[9]: array([1, 2, 3, 4])

b
Out[10]: array([4, 3, 2, 1])

c = Your Answer

c
# desired output: array([14, 23, 32, 41])

My first (and obvious) solution was:

c = np.array([int(''.join (map(str, xs))) for xs in zip(a.tolist(),b.tolist())])

c
Out[12]: array([14, 23, 32, 41])

But I would like to know if it's possible to do that directly with the numpy-arrays, without converting them to python-arrays.

Note: I use 1,2,3,4 values for simplification, I would like to have a solution that work with +double digits on both arrays of size > 10**4.


Updated with timings for different solutions:

a = np.arange(1000000)

b = np.arange(1,1000001)

#: Mi first Solution
%%timeit
c = np.array([int(''.join (map(str, xs))) for xs in zip(a.tolist(),b.tolist())])
1 loop, best of 3: 1.99 s per loop

#: Donkey's Solution (thought to smaller arrays)
%%timeit
c = np.char.add(a.astype(str),b.astype(str)).astype(int)
1 loop, best of 3: 1.8 s per loop

#: My second Solution
%%timeit
c = merge(a,b)
10 loops, best of 3: 128 ms per loop

#: Divakar's Solution
%%timeit
c = a*(10**(np.log10(b).astype(int)+1)) + b
10 loops, best of 3: 117 ms per loop

Verify results:

c1 = np.array([int(''.join (map(str, xs))) for xs in zip(a.tolist(),b.tolist())])

c2 = np.char.add(a.astype(str),b.astype(str)).astype(int)

c3 = merge(a,b)

np.alltrue(np.logical_and(c1==c2,c2==c3))
Out[51]: True


c4 = a*(10**(np.log10(b).astype(int)+1)) + b

np.alltrue(np.logical_and(c1==c2,c2==c4))
Out[58]: True
4
  • 1
    check out the numpy.char module Commented Apr 18, 2016 at 17:49
  • 2
    Try c = 10*a + b Commented Apr 18, 2016 at 17:50
  • I've checked the module and found a quickly answer. Thanks Eelco. Commented Apr 18, 2016 at 17:54
  • Thanks for the comment Andrey, but that operation doesn't return the answer that I want when the 2 arrays contain double digits. Probably my fault the fact of not indicate that I wanted an answer apliccable to double digits also. Commented Apr 18, 2016 at 18:15

3 Answers 3

4

You can use the dtype parameter to have your numpy arrays be string arrays, on which you can simply use the free function add in numpy.char to concatenate them string-wise, like so

a = numpy.array([1,2,3,4], dtype=numpy.str)
b = numpy.array([4,3,2,1], dtype=numpy.str)

c = numpy.char.add(a, b).astype(int)

Outputs:

[14 23 32 41]
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the answer, I was just writing the same solution at the same time ^^
@DaviddelaIglesia Cheers, glad I could help.
I think I found a quite faster solution ^^
2

Here's an approach using NumPy mathematical functions -

a*(10**(np.log10(b).astype(int)+1)) + b

Sample run -

In [32]: a
Out[32]: array([ 16,   2, 399,   4])

In [33]: b
Out[33]: array([  4,  38,   2, 190])

In [34]: a*(10**(np.log10(b).astype(int)+1)) + b
Out[34]: array([ 164,  238, 3992, 4190])

2 Comments

Thanks divakar. I had founded about 10 minutes ago a similar approach. Just like yours but with support to 0s and numbers formed by only 9s.
@DaviddelaIglesia Could you add this to your timings test in the question? Thanks!
1

I write a function with a solution that I found after thinking a while:

def merge(a,b):
#: I don't find a better way to create this array
nines = np.array([9,99,999,9999,99999,999999,9999999, 99999999])

#: get number of digits
exp = np.log10(a)+1

#: fix the zeros
exp[exp == -np.inf] = 1

#: fix the nines
exp[np.in1d(a,nines)] += 1

c = a * 10**exp.astype(int) + b
return c

It might appear to be too much overthinking but it's a lot (x10) faster than the other solutions:

%%timeit
c = merge(a,b)
10 loops, best of 3: 128 ms per loop

3 Comments

I don't think it is any faster, actually. Rather twice as slow. I'd double check your use of timeit.
Ah, no now I see you've tested for 10 million elements. For a smaller case (like your example in your question) the solution I posted is twice as fast.
Sorry about the misleading example, I was trying to simplificate the situation but I should especify wich what kind of arrays I was working at (big and +double digits). I updated the answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.