1

That this answer to Convert numpy ndarray to tuple of tuples in optimize method doens't offer anything more than tuple(tuple(i) for i in a[:,0,:]) suggests this doesn't exist, but I am looking for something like a .totuple() method similar to numpy's .tolist() in that you don't need to know the number of dimensions beforehand to generate a tuple of tuples of tuples...

For my needs this would apply to a float or integer numerical array only.

uhoh
  • 3,713
  • 6
  • 42
  • 95
  • 1
    ``numpy` does not have hidden methods! For most purposes `tolists` is sufficient, and faster than any iteration on an array. It also takes the conversion all the way down, producing python end values (i.e. `int` instead of `np.int64`). – hpaulj Jul 13 '21 at 12:52
  • @hpaulj thanks, I have a hunch that JelleWestra's answer is as good as it's going to get. I'll see if I can make `.tolist()` work for me. If there's no `totupple()` there must be some reason for that. Is there a PEP for [I Do Not Want What I Haven't Got](https://en.wikipedia.org/wiki/I_Do_Not_Want_What_I_Haven%27t_Got)? :-) – uhoh Jul 13 '21 at 13:03
  • 1
    @uhoh You could submit this as a feature request to [numpy](https://github.com/numpy/numpy/issues). – user76284 Mar 13 '23 at 06:50
  • @user76284 after seeing your nice answer I thought about it, but 1) an n-nested tuple is a weird thing, it would then want a shape method of its own (I had to print b[0][0][0][0] to see if b = totuple(np.arange(2**5).reshape(*5*[2])) worked). Usually feature requests need to make a good case for a real need; "What problems/challenges does it solve?" I wouldn't know how to argue such a thing. – uhoh Mar 13 '23 at 07:20
  • 1
    @uhoh One common use case is getting a hashable and immutable representation of an array, e.g. to store in a set or as a key in a dictionary. (In this respect, it's more useful than tolist.) There are many questions on SO about converting an array to a nested tuple. These could perhaps be used as examples. – user76284 Mar 13 '23 at 15:38

2 Answers2

2

You can make use of a recursive function which converts to a tuple independent of the number of dimensions:

def totuple(a):
    try:
        return tuple(totuple(i) for i in a)
    except TypeError:
        return a

Found in this answer: Convert numpy array to tuple

Jelle Westra
  • 526
  • 3
  • 8
  • Interesting! I will give it a try. I was hoping for "something like a `.totuple()` *method* similar to numpy's `.tolist()`" so I wouldn't have to rewrite it every time I need it, but it may not exist. – uhoh Jul 13 '21 at 12:08
  • 1
    @uhoh As far as I'm aware, there doesn't exist such a method or function in numpy unfortunately. – Jelle Westra Jul 13 '21 at 12:13
  • Applying this function to the `tolist` result is probably faster. – hpaulj Jul 13 '21 at 12:54
2

A more explicit alternative:

def totuple(a):
    if a.shape == ():
        return a.item()
    else:
        return tuple(map(totuple, a))

Example:

import numpy as np
a = np.arange(3 * 4).reshape(3, 4)
print(totuple(a))
((0, 1, 2, 3), (4, 5, 6, 7), (8, 9, 10, 11))
user76284
  • 1,269
  • 14
  • 29
  • 1
    Nice! [Zen of Python 'Explicit is better than implicit'](https://stackoverflow.com/q/64070128/3904031) – uhoh Mar 13 '23 at 07:13