Assuming this list
nestedList = ["a", "b", [1, 2, 3], "c",[4, 5, 6, [100, 200, 300]], "d"]
I have a function that returns a position list for a nested list of arbitrary depth.
Examples:
[2, 1] -> "2"
[5] -> "d"
[4, 3, 2] -> "300"
As you can see it is not clear in the beginning how many levels of nesting there are.
Additional Problem
For list modifications I want to use the [:] or [4:] or [0:1] notations.
For a human its very easy to do: simply add as many index position as you need to.
nestedList[2][1]
nestedList[5]
nestedList[4][3][2]
nestedList[4][1:] = NewItem + nestedList[4][1:] #insert item
nestedList[2][1] = [] #remove item
However this approach does not lead anywhere since I had to append strings together and eval them later. Obvious nonsense 🙂
What is the best way to handle a nested list with an unknown number of index positions and still have the functionality to handle it like a normal list (read, modify, insert, remove)
I hope there is an answer to that.
P.S. the list must remain nested. Flattening is not an option.
I finally had some time to fiddle around with this. I got a little carried away. It’s long, but I’m pasting it anyway. I added
set_item,insert,delete,find, andfind_leftmethods, as well as some private methods to allow low-level manipulation that breaks the cursor abstraction. I also added amove_cursormethod that throws anIndexErrorfor index tuples that are out of range or point to a non-toplevel object.Basically, it (should) be guaranteed that as long as you use public functions only, the cursor always points to a top-level object, and insertions and deletions all happen at the top level. From here, you should be able to safely implement
__getitem__,__setitem__,__delitem__, etc, and maybe even__getslice__,__setslice__.However, there are a couple of wrinkles. The restriction that the cursor always points to a toplevel object makes it very easy to iterate over the nested list as though it were a flat list. But it also means that the cursor can’t point at lower-level objects, and hence some kinds of insertions can’t happen using
insertalone. For example, say you have three lists:Now put this nested structure in a NLI, move to
5, and try to insert.As you can see, you can insert something into
l2, but you can’t easily insert something intol3. In fact, to do so right now, you have to use a private function, which breaks the cursor abstraction in an unpleasant way:There are surely ways to implement a safe public
insert_between_branchesmethod, but they involve more complication than I care to bother with right now.Another problem appears when one tries to insert a value after
4. As you’ve seen, you can insert a value intol2before5, but if you move the cursor to4andinsert, you’ll quickly realize that you can’t insert something after4insidel1.From the perspective of flat access, inserting after 4 and inserting before 5 are the same thing, but from the perspective of the nested list, they are different. Since
insertis effectively aleft_insert, this problem could be partially rectified with aright_insertmethod (which would, in turn, be unable to insert at the beginning of l1).These problems could probably be dealt with more generally by allowing the cursor to point to lower-level objects, but that would make flat access more complicated. In short, any attempt to rectify these problems will lead to greater complexity, either on the flat or the nested side of the interface.
(That is actually why I still prefer the simple
enumerate_nestedmethod! A proper tree structure with values at all nodes (and not just top-level nodes) might also be simpler and better. But this was fun to code nonetheless.)