仅通过提供“left()"来使用光标手动导航嵌套列表.和“right()"作为命令?

问题描述

尽管我用 python 编写,但我认为抽象概念对我和其他人来说更有趣.所以如果你喜欢,请伪代码:)

Eventhough I write in python I think the abstract concept is more interesting to me and others. So pseudocode please if you like :)

我有一个列表,其中包含我的一个班级的项目.让我们在这里用字符串和数字来做,这真的没关系.它嵌套到任何深度.(它实际上不是一个列表,而是一个基于列表的容器类.)

I have a list with items from one of my classes. Lets do it with strings and numbers here, it really doesn't matter. Its nested to any depth. (Its not really a list but a container class which is based on a list.)

示例:[1, 2, 3, ['a', 'b', 'c'] 4 ['d', 'e', [100, 200, 300]] 5, ['a', 'b', 'c'], 6]

请注意,两个 ['a', 'b', 'c'] 实际上是同一个容器.如果你改变一个,你就会改变另一个.可以编辑容器和项目,插入项目,最重要的容器可以多次使用.为避免冗余,不可能展平列表(我认为!),因为您失去了在一个容器中插入项目的能力,它会自动出现在所有其他容器中.

Note that both ['a', 'b', 'c'] are really the same container. If you change one you change the other. The containers and items can be edited, items inserted and most important containers can be used multiple times. To avoid redundancy its not possible to flatten the list (I think!) because you loose the ability to insert items in one container and it automatically appears in all other containers.

问题: 对于前端(只是带有 pythoncmd"模块的命令行),我想使用始终指向当前项目的光标导航此结构,以便可以读取或编辑.光标可以左右移动(用户的观点),并且应该表现得像列表不是嵌套列表而是平面列表.

The Problem: For the frontend (just commandline with the python "cmd" module) I want to navigate through this structure with a cursor which always points to the current item so it can be read or edited. The cursor can go left and right (users point of view) and should behave like the list is not a nested list but a flat one.

对于人类来说,这非常容易做到.你只是假装在上面的这个列表中子列表不存在,然后简单地从左到右再返回.

For a human this is super easy to do. You just pretend that in this list above the sublists don't exist and simply go from left to right and back.

例如,如果您在上面列表中的3"位置并向右走,您将获得a"作为下一项,然后是b"、c",然后是4"等.或者,如果您直接从300"开始,您会得到下一个5".

For example if you are at the position of "3" in the list above and go right you get 'a' as next item, then 'b', 'c', and then "4" etc. Or if you go right from the "300" you get the "5" next.

反过来:如果你从6"向左走,下一个是c".如果你从5"向左走,它的300".

And backwards: If you go left from "6" the next is 'c'. If you go left from "5" its "300".

那么原则上我该怎么做呢?我在这里有一种方法,但它是错误的,而且问题已经很长了,我担心大多数人不会阅读它:(.我可以稍后发布.

So how do I do that in principle? I have one approach here but its wrong and the question is already so long that I fear most people will not read it :(. I can post it later.

附:即使很难抗拒:这个问题的答案不是为什么要这样做,为什么要以这种方式组织数据,为什么不先[扁平化列表|超出我的想象]?问题正是我在这里所描述的,仅此而已.数据是按照问题的性质以这种方式构建的.

P.S. Even if its hard to resist: The answer to this question is not "Why do you want to do this, why do you organize your data this way, why don't you [flatten the list| something out of my imagination] first? The problem is exactly what I've described here, nothing else. The data is structured by the nature of the problem this way.


解决方案

一种解决方案是存储当前索引和/或深度信息并使用它来遍历嵌套列表.但这似乎是一个会进行很多复杂分叉的解决方案——测试列表的结尾,等等.相反,我想出了一个妥协方案.我没有扁平化列表列表,而是创建了一个生成器,它在列表列表中创建一个扁平的索引列表:

One solution would be to store current index and/or depth information and use it to traverse the nested list. But that seems like a solution that would do a lot of complicated forking -- testing for ends of lists, and so on. Instead, I came up with a compromise. Instead of flattening the list of lists, I created a generator that creates a flat list of indices into the list of lists:

def enumerate_nested(nested, indices):
    for i, item in enumerate(nested):
        if isinstance(item, collections.Iterable) and not isinstance(item, basestring):
            for new_indices in enumerate_nested(item, indices + (i,)):
                yield new_indices
        else:
            yield indices + (i,)

然后是一个简单的函数,它根据索引元组从列表列表中提取最里面的项目:

Then a simple function that extracts an innermost item from the list of lists based on an index tuple:

def tuple_index(nested_list, index_tuple):
    for i in index_tuple:
        nested_list = nested_list[i]
    return nested_list

现在您所要做的就是以任何您喜欢的方式遍历平面索引列表.

Now all you have to do is traverse the flat index list, in whatever way you like.

>>> indices = list(enumerate_nested(l, tuple()))
>>> print l
[1, 2, 3, ['a', 'b', 'c'], 4, ['d', 'e', [100, 200, 300]], 5, ['a', 'b', 'c'], 6]
>>> for i in indices:
...     print tuple_index(l, i),
... 
1 2 3 a b c 4 d e 100 200 300 5 a b c 6

<小时>

由于我在评论中发布在 ideone 上的基于堆栈的解决方案已接受此答案,并且由于最好不要使用外部粘贴箱作为答案代码,因此请注意 这个答案包含我的基于堆栈的解决方案.


Since this answer was accepted for the stack-based solution that I posted on ideone in the comments, and since it's preferable not to use external pastebins for answer code, please note that this answer also contains my stack-based solution.

相关文章