Your first line is wrong:
In [172]: myArray = np.array(['A','B'],['A','C'],['B','C'])
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Input In [172], in <cell line: 1>()
----> 1 myArray = np.array(['A','B'],['A','C'],['B','C'])
TypeError: array() takes from 1 to 2 positional arguments but 3 were given
With the correct arguments:
In [173]: myArray = np.array((['A','B'],['A','C'],['B','C']))
In [174]: for row in myArray: print(row)
['A' 'B']
['A' 'C']
['B' 'C']
In [175]: myArray.shape, myArray.dtype
Out[175]: ((3, 2), dtype('<U1'))
This is NOT an array of lists. It is a 2d array of strings. Simple iteration is enough to get the rows. In the above iteration row
is a 1d array of strings, not a list.
In [176]: type(row)
Out[176]: numpy.ndarray
nditer
iterates on the elements of an array, regardless of the dimensions. Trying to do the equivalent of a simple iteration may be possible, but it's tricky and not worth the effort.
In [179]: with np.nditer(myArray) as comb:
...: for i in comb:
...: print(i, type(i), i.shape)
...:
A <class 'numpy.ndarray'> ()
B <class 'numpy.ndarray'> ()
A <class 'numpy.ndarray'> ()
C <class 'numpy.ndarray'> ()
B <class 'numpy.ndarray'> ()
C <class 'numpy.ndarray'> ()
The items of the nditer
iteration are 0d arrays.
The nditer
docs mention the uses of multiindex
if you want to track the multidimensional indices of the iteration.
If you really want nditer
to iterate on "rows" you need to make a 1d object dtype array - an array of arrays:
In [189]: arr = np.empty(3,object); arr[:] = list(myArray)
In [190]: arr
Out[190]:
array([array(['A', 'B'], dtype='<U1'), array(['A', 'C'], dtype='<U1'),
array(['B', 'C'], dtype='<U1')], dtype=object)
or array of lists:
In [191]: arr = np.empty(3,object); arr[:] = myArray.tolist()
In [192]: arr
Out[192]: array([list(['A', 'B']), list(['A', 'C']), list(['B', 'C'])], dtype=object)
And you still need to supply a "REFS_OK" flag. But even here, nditer
has no benefit compared to a simple loop iteration (or better yet no-loop numpy operations.
In short nditer
is not a substitute for loops.
edit
With an array of lists:
In [202]: arr = np.empty(3,object); arr[:] = myArray.tolist()
In [203]: arr
Out[203]: array([list(['A', 'B']), list(['A', 'C']), list(['B', 'C'])], dtype=object)
In [204]: with np.nditer(arr, ['refs_ok']) as comb:
...: for i in comb:
...: print(i, type(i), i.shape)
...:
['A', 'B'] <class 'numpy.ndarray'> ()
['A', 'C'] <class 'numpy.ndarray'> ()
['B', 'C'] <class 'numpy.ndarray'> ()
Here each iteration i
is a 0d array containing a list object.
With an array of arrays (not 2d), the iteration object is still 0d, but it contains arrays (not the missing commas).
In [207]: arr
Out[207]:
array([array(['A', 'B'], dtype='<U1'), array(['A', 'C'], dtype='<U1'),
array(['B', 'C'], dtype='<U1')], dtype=object)
In [208]: with np.nditer(arr, ['refs_ok']) as comb:
...: for i in comb:
...: print(i, type(i), i.shape,i.dtype, i.item())
...:
['A' 'B'] <class 'numpy.ndarray'> () object ['A' 'B']
['A' 'C'] <class 'numpy.ndarray'> () object ['A' 'C']
['B' 'C'] <class 'numpy.ndarray'> () object ['B' 'C']
Taking a hint from https://numpy.org/doc/stable/reference/arrays.nditer.html#buffering-the-array-elements, I can do:
In [213]: with np.nditer(myArray.T.copy(), ['external_loop'], order='F') as comb:
...: for i in comb:
...: print(i, type(i), i.shape)
...:
['A' 'B'] <class 'numpy.ndarray'> (2,)
['A' 'C'] <class 'numpy.ndarray'> (2,)
['B' 'C'] <class 'numpy.ndarray'> (2,)