Python 当没有可靠的顺序,但需要访问和检查最低级别的所有元素时,如何迭代嵌套数据?

Python 当没有可靠的顺序,但需要访问和检查最低级别的所有元素时,如何迭代嵌套数据?,python,nested,iteration,Python,Nested,Iteration,我在一个非常具体的背景下遇到了这个问题,但我很快意识到它具有相当普遍的相关性 仅供参考:我从一个框架中获取数据,并在某一点上将其转换为无序对的列表(可以是任何大小的列表或元组列表,但atm除外。我有100%对)。在我的例子中,这些对表示数据对象之间的关系,我想优化我的数据 我有一个无序元组列表,想要一个对象列表,或者在本例中是一个dict of dict。如果相同的字母表示相同的类,不同的数字表示不同的实例,我希望完成此转换: [(a1, x1), (x2, a2), (y1, a2), (y1

我在一个非常具体的背景下遇到了这个问题,但我很快意识到它具有相当普遍的相关性

仅供参考:我从一个框架中获取数据,并在某一点上将其转换为无序对的列表(可以是任何大小的列表或元组列表,但atm除外。我有100%对)。在我的例子中,这些对表示数据对象之间的关系,我想优化我的数据

我有一个无序元组列表,想要一个对象列表,或者在本例中是一个dict of dict。如果相同的字母表示相同的类,不同的数字表示不同的实例,我希望完成此转换:

[(a1, x1), (x2, a2), (y1, a2), (y1, a1)] -> {a1:{"y":y1,"x":x1},a2:{"y":y1,"x":x2}}
请注意,可以有许多“a”连接到同一个“x”或“y”,但每个“a”最多都有一个“x”或“y”,并且我不能依赖元组的顺序或元组元素的顺序(因为框架对“a”和“x”没有区别)很明显,我不关心我的字典中元素的顺序,我只需要正确的关系。还有很多我不关心的对,它们也可以包含“a”元素、“y”元素或“x”元素

因此,主要的问题是“当没有可靠的顺序,但需要访问和检查最低级别的所有元素时,如何迭代嵌套数据?”

我试了好几种方法,但似乎都不对。为简单起见,我只在此处检查A-X对:

def first_draft(list_of_pairs):
    result = {}
    for pair in list_of_pairs:
        if pair[0].__cls__ is A and pair[1].__class__ is X:
            result[pair[0]] = {"X": pair[1]}
        if pair[0].__cls__ is X and pair[1].__class__ is A:
            result[pair[1]] = {"X": pair[0]}
    return result

def second_draft(list_of_pairs):
    result = {}
    for pair in list_of_pairs:
        for index, item in enumerate(pair):
            if item.__cls__ is A:
                other_index = (index + 1) % 2
                if pair[other_index].__class__ is X:
                    result[item] = {"X":pair[other_index]}
    return result

def third_draft(list_of_pairs):
    result = {}
    for pair in list_of_pairs:
        for item in pair:
            if item.__class__ is A:
                for any_item in pair:
                    if any_item.__class__ is X:
                        result[item] = {"X":any_item}
    return result
第三个草稿实际上适用于每种大小的子列表,并且消除了任何非python整数用法,但是在迭代自身的同时迭代相同的列表?一行代码的五重嵌套?这在我看来并不正确,我学到了“当python中的迭代出现问题时,您不知道一个好的解决方案-itertools中有一个很好的解决方案!”-我只是没有找到一个。

现在是否有人开发了一个可以帮助我的构建,或者仅仅是一种更好的方法来实现我的方法?

您可以使用字符串执行以下操作:

l = [('a1', 'x1','z3'), ('x2', 'a2'), ('y1', 'a2'), ('y1', 'a1')]
res = {}

for tup in l:
    main_class = ""
    sub_classes = ""
    for item in tup:
        if item.startswith('a'):
            main_class = item
    sub_classes = list(tup)
    sub_classes.remove(main_class)

    if not main_class in res:
        res[main_class] = {}


    for item in sub_classes:
        res[main_class][item[0]] = item[-1]
如果对象不是字符串,则只需将a.startswith('a'):更改为确定对中的第一项是否应为键的内容

这也处理长度大于2的元组。它迭代每个元组,找到“主类”,然后将其从元组的列表版本中删除(这样新的列表就是所有的子类)。

看起来像Ned Batchelder(他说每次有iterables问题时,都认为Python中没有好的解决方案,itertools中有解决方案)是正确的。我终于找到了一个上次忽略的解决方案:排列法

def final_draft(list_of_pairs):
    result = {}
    for pair in list_of_pairs:
        for permutation in permutations(pair):
            if permutation[0].__class__ is A:
                my_a = permutation[0]
                if permutation[1].__class__ is X:
                    my_x = permutation[1]
                    if my_a not in result:
                        result[my_a] = {}
                    result[my_a]["key for X"] = my_x
    return result
我仍然有五元组嵌套,因为我添加了一个键是否存在的检查(因此我的原始草稿将有六元组嵌套和两行有效的代码),但我放弃了对同一个iterable的双重迭代,并且具有最小的索引使用量和将来使用三元组的可能性。

人们可以避免赋值,但我更喜欢排列[0]之前的“my_a”

其中
b
来自您想要的输出
[(a1,x1),(x2,a2),(y1,a2),(y1,a1)]->{a:{“y”:y1,“x”:x1},b:{“y”:y1,“x”:x2}
?在决定使用a1,a2而不是a,b--修复了什么
a1
x1,
a2
<代码>str
对象,某类对象还是什么?它们应该用引号括起来吗?它们是对象。我只是在示例中引用了“X”,因为输出dict有X类型的字符串键
{a1:{“X-或任何其他字符串”:x1}
OP说它们不是字符串而是对象。如果只有这两个类的对,但我得到了0到2(或3)个所需类的对(很快可能是3元组)。我必须检查低层集合中每个对象的类。更新以处理更大的元组(尽管我刚刚注意到您已经解决了问题:))为了优化性能,您可以在末尾添加一个
中断
,如果置换[1]。\uu class\uuuuuuuuuuuu是X:
块以跳过废弃置换。