【问题标题】:Update list using dictionary when values are lists of different lengths当值是不同长度的列表时使用字典更新列表
【发布时间】:2020-04-01 16:33:48
【问题描述】:

*** 更新 **** 额外的字母“A”是个问题。我在这里重新表述一下。也许更清楚? 我必须使用具有可变长度列表作为其值的字典来替换列表中的值。例如:

variants = {C:["cat", "can", "car"], D:["do","die"], Z:["zen", "zoo"]}

还有一个清单:

Letters = ["C", "D", "Z"]

我想要这样的列表输出

PotentialWords = [["cat", "do", "zen"], ["can", "die", "zoo"],["car", "do", "zen"], ["car", "die", "zoo"]

所有元素在每一步都得到更新,但如果 索引超过,则 更新被保留,我们得到所有变体相互交叉。

到目前为止我所拥有的是:

max_len = max([len(words) for words in variants.values()])

for i in range(max_len):
    var = []
    for let in Letters:
        if let not in variants.keys():
           var.append(let)
        else:
            if i < len(variants[let]):
              var.append(variants[let][i])
            elif i > len(variants[let]):
              var.append(let)

这给出了错误的输出:

OutputWords = [["cat", "do", "zen"], ["can", "die", "zoo"], ["car"]]

您的所有帮助将不胜感激 :) * 更新* 感谢评论者,此问题已更新以更清晰。以前的输入是

Letters = ["C", "D", "Z", "A"]

然后输出

[["cat", "do", "zen", "A"], ["can", "die", "zoo","A"],["car", "A"]]

** 请只看上面的输入/输出

【问题讨论】:

  • 您能否进一步解释在给定输入的情况下获取输出的公式?为什么"A" 在那里?为什么输出长度为 4?为什么不是第三个["car", "D", "Z", "A"]
  • 感谢您的回复! “A”是必需的,因为有些字母会有变体,而有些则没有。那些没有的,将需要保留。第三个不是["car", "D", "Z", "A"],因为嵌套了elif 循环。如果我可以在最后两行做else: var.append(let),那么我们就会得到那个输出。但这仍然不是我们想要的。 :(
  • 这段代码的用途尚不清楚。为什么要将字母添加到字典中?
  • 除了@blueteeth 的评论:您想选择字典中给出的列表的第 i 个元素。考虑到i=2,从第一个列表中选择car,并且由于其他两个列表都不包含那么多元素,因此在其他列表上“溢出”。我想,我到此为止。但是,我不明白如何从字母列表中选择A。从我的角度来看,i=2 你应该从这个列表中选择Z
  • 我刚刚添加了对代码的编辑。请问现在可以看吗?我为之前的混乱道歉。我已经删除了A,将单独处理。非常感谢所有的澄清和理解。是的,问题出在“溢出”上。

标签: python python-3.x list dictionary variable-length-array


【解决方案1】:
0   1   2   3
a0  a1  a2
b0  b1  b2  b3
c0  c1

假设您有这些列表,并且字母是 [a, b, c],我认为您要做的是将所有内容填充到与最长相同的长度,然后压缩所有内容。

所以它会变成这样,然后你可以阅读列

0   1   2   3
a0  a1  a2  a0
b0  b1  b2  b3
c0  c1  c0  c1

如果这是你想做的,这能解决吗?

max_len = max([len(words) for words in variants.values()])
results = []
for i in range(max_len):
    var = []
    for let in Letters:
        index = i % len(Letters[let])
        var.append(Letters[let][index])
    results.append(var)

【讨论】:

  • 非常感谢您提供这种出色的表现方式。请允许我根据我的数据对其进行测试并返回给您。
【解决方案2】:

函数式编程的力量开始发挥作用。我使用了itertoolscycleislicezip 的众所周知的功能:

from itertools import cycle, islice
variants = {"C":["cat", "can", "car"], "D":["do","die"], "Z":["zen", "zoo"]}
letters = ["C", "D", "Z"]

def take_first_n_items(iterable, n):
    return list(islice(iterable, max_len)) 

max_len = max([len(words) for words in variants.values()])
phrase_iterables = [cycle(variants[letter]) for letter in letters]
full_values_of_variants = [take_first_n_items(iterable, max_len) for iterable in phrase_iterables]
results = list(zip(*full_values_of_variants))
print(results)

它是如何工作的:

#phrase_iterables = [('cat', 'can', 'car','cat',...), ('do', 'die', 'do', ...) , ('zen', 'zoo', 'zen', 'zoo',...)]
#full_values_of_variants = [['cat', 'can', 'car'], ['do', 'die', 'do'], ['zen', 'zoo', 'zen']]

输出:[('cat', 'do', 'zen'), ('can', 'die', 'zoo'), ('car', 'do', 'zen')]

注意:list(islice(iterable, max_len)) 使用了不必要的额外迭代。您可以将其替换为 islice(iterable, max_len)

【讨论】:

  • 非常感谢您介绍这种新方法。所需的输出为[('cat', 'do', 'zen'), ('can', 'die', 'zoo'), ('car', 'do', 'zen'), ('car', 'die', 'zoo')]。错过最后一个值是否有原因?我将检查我的数据,处理您的代码并返回给您。
  • 我不确定您是如何获得以“汽车”开头的额外术语的?我的循环在具有最大长度的变体值的最后一项内完成。因此我的数组只有三个项目。
  • 您好,非常感谢您的回复。仅字母“C”就有 3 个变体。其他人有 2 个。我希望得到字母 C(汽车)的第 3 个变体,应该附加到前面字母的两个变体(do/die,zen/zoo)。现在,它似乎附加到第一个。这有意义吗?
  • 是的,确实如此。但是还有什么其他字母?他们不应该同时拥有两种变体(do/die、zen/zoo)吗?
  • 我的意思是,为什么不在相同的逻辑中包含案例('cat'、'die'、'zoo')、('can'、'do'、'zen')?
【解决方案3】:

我会通过图表来解决这个问题。想象每个列表在图中处于某个深度级别。

     root
   /  |  \
 cat can  car
  |\  /|\ /|
 do   die
  |\  /|
 zen zoo

在这里,我们假设根元素“root”和列表Letters 是每个列表在图中出现的顺序。所以C : [cat, can, car] 将位于深度 1,D: [do, die] 将位于级别 2..等等。

我们可以使用以下函数轻松创建这个无向图:

variants = {"C":["cat", "can", "car"], "D":["do","die"], "Z":["zen", "zoo"]}

Letters = ["C", "D", "Z"]

def create_graph(list_dict, depth_order):
  graph = {"root": set(list_dict[depth_order[0]])}
  for i in range(1, len(depth_order)):
    parents = list_dict[depth_order[i-1]]
    children = list_dict[depth_order[i]]
    # Connect parent to children
    for elem in parents:
      graph[elem] = set(children)
    # Connect children tp parent
    for elem in children:
      graph[elem] = set(parents)
  return graph

graph = create_graph(variants, Letters)
print(graph)

请注意,每个级别如果完全连接到下一个级别。因此,如果我们找到从第 1 层中的一个元素到最后一层中的另一个元素的路径,我们会找到组合的所有变体。我们可以简单地使用深度优先搜索 (link)

def dfs_paths(graph, start, goal):
  stack = [(start, [start])]
  while stack:
    (vertex, path) = stack.pop()
    for next in graph[vertex] - set(path):
      if next == goal:
        yield path + [next]
      else:
        stack.append((next, path + [next]))

现在我们可以使用所需的开始和结束节点调用此函数:

print(list(dfs_paths(graph, 'cat', 'zen')))

这会产生:

[['cat', 'die', 'zen'], ['cat', 'die', 'zoo', 'do', 'zen'], ['cat', 'do', 'zen'], ['cat', 'do', 'zoo', 'die', 'zen']]

我们可以过滤此列表以仅包含长度 = len(Letters) 的元素,这将消除 DFS 跟踪上一级的间接路径。

输出:

[['cat', 'die', 'zen'], ['cat', 'do', 'zen']]

让我知道它是否适合您。干杯!

【讨论】:

    猜你喜欢
    • 2022-11-27
    • 1970-01-01
    • 1970-01-01
    • 2019-08-12
    • 2017-11-30
    • 2020-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多