在列表中循环显示潜在结果时遇到问题

Having trouble looping over potential outcomes in a list

提问人:iceman 提问时间:5/10/2023 更新时间:5/11/2023 访问量:45

问:

我有以下代码,可以遍历现有列表中的每个子列表。因此,它添加每个元素的最后一个元素,并将其从 A-B 映射到每个子列表上。

existing_list = [[1, 2, 3, 4], [2, 3, 4]]
A = [4,5, 6]
B = [5,6, 7]

for i in range(len(existing_list)):
    sublist = existing_list[i]
    for j in range(len(A)):
        if sublist[-1] == A[j]:
            sublist.append(B[j])

print(existing_list)

[[1, 2, 3, 4, 5, 6, 7], [2, 3, 4, 5, 6, 7]]

假设我现在想向 A、B 添加重复的元素,但我想为每个元素创建一个唯一的路径。我很难理解从这里去哪里。

如果我将以下元素更改为 A/B,我想要的输出是。

existing_list = [[1, 2, 3, 4], [2, 3, 4]]
A = [4,4,5, 6]
B = [5,6,6, 7]


[[1, 2, 3, 4, 5, 6, 7],[1, 2, 3, 4, 6, 7], [2, 3, 4,5, 6, 7],[2, 3, 4, 6, 7]]

需要帮助循环并制作新列表。对不起,这是我的第一篇文章,如果太密集,我深表歉意。如果您有任何问题,请告诉我。

Python 列表 while 循环 映射

评论

0赞 SimonUnderwood 5/10/2023
您能详细说明一下“向 A、B 添加重复的元素,但我想为每个元素创建一个唯一的路径”是什么意思吗?此外,您展示的这个示例看起来很随意且毫无意义。如果这是对你试图解决的更具体问题的简化,也许告诉我们原来的问题会更好,因为我根本不知道你要完成什么。
0赞 iceman 5/10/2023
是的,西蒙,对于一个更大的数据集来说,这是一个简化的问题。从本质上讲,我有一个现有的数据集,其中包含来自 A-B(现有列表)的数千条路径。给定每个点 (A&B) 的数据基本数据映射,我本质上是在尝试为连接路径的每个可能点创建一条唯一的路径。因此,通过向运行的第一个代码添加重复的比较,我想创建一个新的唯一路径。对于复杂性,我们深表歉意。A: 中的重复元素是额外的 4,6,与它们唯一的 1 条路径和 4 是 4,5 相比。

答:

0赞 oli26 5/10/2023 #1

你可以像这样使用递归函数:

existing_list = [[1, 2, 3, 4], [2, 3, 4]]

A = [4,4,5, 6]
B = [5,6,6, 7]


def map_multiple(sublist):
    subsets = []
    anyMatches = False
    for (key, value) in zip(A, B):
        if key == sublist[-1]:
            new_sets = map_multiple(sublist + [value])
            subsets.extend(new_sets)
            anyMatches = True
    if not anyMatches:
        return [sublist]
    return subsets

new_list = []
for i in range(len(existing_list)):
    sublist = existing_list[i]
    allSubsets = map_multiple(sublist)
    new_list.extend(allSubsets)

print(new_list)

评论

1赞 oli26 5/10/2023
只要确保没有 n -> n,否则你的程序将进入无限循环。
0赞 SimonUnderwood 5/10/2023 #2

由于 和 是路径的映射,我将它们解析到字典中。然后,我使用递归函数遍历所有可能的路径,无论分支出现在哪里。AB

existing_list = [[1, 2, 3, 4], [2, 3, 4]]
A = [4,4,5, 6]
B = [5,6,6, 7]

pathways = {}
for a, b in zip(A, B):
    if a not in pathways:
        pathways[a] = [b]
    else:
        pathways[a].append(b)

# creates a dict like this:
# paths = {
#     4: [5, 6],
#     5: [6],
#     6: [7]
# }

def get_paths(starting_path_list: list, pathways: dict) -> list[list]:
    all_path_lists = []

    while (end_num := starting_path_list[-1]) in pathways:
        if len(pathways[end_num]) == 1: # no branching
            starting_path_list += pathways[end_num]
        else:
            for path in pathways[end_num]: # branching
                all_path_lists += get_paths(starting_path_list + [path], pathways) # recursive call
            break
    else: # triggers if while loop ends without break
        all_path_lists.append(starting_path_list)
        
    return all_path_lists

new_list = []
for sublist in existing_list:
    new_list += get_paths(sublist, pathways)

print(new_list)
# prints: [[1, 2, 3, 4, 5, 6, 7],[1, 2, 3, 4, 6, 7], [2, 3, 4,5, 6, 7],[2, 3, 4, 6, 7]]

与所有递归一样,您需要注意不要创建无限循环。在这里,您需要确保路径中没有任何圆形结构。

0赞 Alain T. 5/11/2023 #3

如果要在非常大的列表上执行此操作,则可能需要使用字典来利用对子列表的直接访问。

例如:

  • 构建一个包含子列表的字典,其键与每个子列表中的最后一个数字相对应。请注意,可能有多个以相同值结尾的子列表。因此,该字典中的值将是子列表(以相同的值结尾)
  • 此 () 字典将允许您在添加 a->b 链接后通过将子列表从一个结束键移动到另一个结束键来扩展子列表。ends
  • 它还允许您在链接到多个 s 时将多个副本添加到同一个结束键ab
  • 为了简化 A->B 链接的处理,您可以形成一个字典,其中每个不同的链接作为键,并将相应的 s 列表作为值 (abABPaths)
  • 使用这两个字典,扩展过程将简单地将所有以值结尾的列表移动到所有结束键(S),以获得任意数量的值(这将隐式创建重复路径)abb
  • 最后,字典中的值将是所有路径ends

...

existing_list = [[1, 2, 3, 4], [2, 3, 4]]
A = [4,4,5,6]
B = [5,6,6,7]

ends = dict()
for sublist in existing_list:
    ends.setdefault(sublist[-1],[]).append(sublist)

print(ends) # {4: [[1, 2, 3, 4], [2, 3, 4]]}

ABPaths = dict()
for a,b in zip(A,B):
    ABPaths.setdefault(a,[]).append(b)

print(ABPaths) # {4: [5, 6], 5: [6], 6: [7]}

for a,bs in ABPaths.items():
    aEnds = ends.pop(a)
    for b in bs:
        ends.setdefault(b,[]).extend( e+[b] for e in aEnds )

existing_list = [p for paths in ends.values() for p in paths]

print(existing_list)
# [[1, 2, 3, 4, 6, 7], [2, 3, 4, 6, 7], [1, 2, 3, 4, 5, 6, 7], 
   [2, 3, 4, 5, 6, 7]]

请注意,这假设 A->B 链接仅指向更大的数字(即 B 中的每个值都大于 A 中的相应值),这在您的示例中是正确的,但在您的实际数据中可能不是这样