1

I'm trying to make a 3D-array where each element references the current row, column and item. So if I have x=[0,1], y=[0,1,2] and item=['a','b'], I wish the output to be

arr = [ [ [00a, 10a], [01a, 11a], [02a, 12a] ], 
[ [00b, 10b], [01b, 11b], [02b, 12b] ]]

I know that this can be easily done with a triple loop as such

for i in range(len(x)):
  for j in range(len(y)):
    for it in range(len(item)):
      arr[i,j,it] = str(i)+str(j)+it

but is there a more elegant way to do it, for example with some numpy command? Thanks!

Ella
  • 35
  • 4
  • I do not know if numpy has such a command, but you could also use list comprehension if you want a better performance. – David Duran Jul 18 '20 at 13:31
  • What are you trying to improve? – wwii Jul 18 '20 at 13:38
  • @wwii I want to know if there is an easier way of doing this, preferable something that can be done with less lines. – Ella Jul 18 '20 at 13:41
  • @DavidDuran How would I use list comprehension? – Ella Jul 18 '20 at 13:42
  • 1
    @MrNobody33 has given you the answer using list comprehension – David Duran Jul 18 '20 at 13:51
  • 1
    related: [Replace Nested For Loops… or not](https://stackoverflow.com/questions/482146/replace-nested-for-loops-or-not), [Single Line Nested For Loops](https://stackoverflow.com/questions/17006641/single-line-nested-for-loops). - when you searched for solutions for replacing nested for loops why were none of the search results acceptable.? – wwii Jul 18 '20 at 13:51

2 Answers2

4

You can use list comprehension:

arr=[[[f'{i}{j}{k}' for k in item]for j in y]for i in x]

Output:

arr
[[['00a', '00b'], ['01a', '01b'], ['02a', '02b']],
 [['10a', '10b'], ['11a', '11b'], ['12a', '12b']]]

Antoher option using itertools and numpy:

import itertools 
import numpy as np
prod=itertools.product(x,y,item)
prod=list(map(lambda x: f'{x[0]}{x[1]}{x[2]}',prod))
np.array(prod).reshape(len(x),len(y),len(item))

Output:

array([[['00a', '00b'],
        ['01a', '01b'],
        ['02a', '02b']],

       [['10a', '10b'],
        ['11a', '11b'],
        ['12a', '12b']]], dtype='<U3')
MrNobody33
  • 6,413
  • 7
  • 19
1

Here is another solution without loops using numpy:

import numpy as np

x=np.array([0,1]).astype(str)
y=np.array([0,1,2]).astype(str)
items=np.array(['a','b'])


temp= np.core.defchararray.add(y[:,np.newaxis], items)
result = np.core.defchararray.add(x[:,np.newaxis,np.newaxis], temp)

print(result)

output:

[[['00a' '00b']
  ['01a' '01b']
  ['02a' '02b']]

 [['10a' '10b']
  ['11a' '11b']
  ['12a' '12b']]]
Roland Deschain
  • 2,211
  • 19
  • 50
  • 1
    In my experience `defchararray` functions are not fast. They still use python string methods, one element at a time. – hpaulj Jul 18 '20 at 15:05