【问题标题】:Filter unique combination in the list of dictionaries过滤字典列表中的唯一组合
【发布时间】:2019-05-15 19:51:23
【问题描述】:

所以,我得到了一个充满字典的列表,其中我有两个名字(name00 和 name01)。这些是链接集群的名称,并且总是有所有可用的组合。可以从 2 个或更多集群创建组合,并且可以在结果变量中提供更多组合。

在这个例子中,我链接了具有 3 个不同名称 (1,2,3) 和 2 个不同名称 (4,5) 的集群,但它可以更多。

我需要过滤结果,所以我只得到唯一的组合(name00 和 name01 两种方式)并且只用于其中一个集群。例如,如果选择test1作为main,我们可以丢弃示例中的test2-test3组合。

我希望这个例子能说明问题。

results = [
{ 'name00': 'test1', 'name01': 'test2' },
{ 'name00': 'test1', 'name01': 'test3' },
{ 'name00': 'test2', 'name01': 'test1' },
{ 'name00': 'test2', 'name01': 'test3' },
{ 'name00': 'test3', 'name01': 'test1' },
{ 'name00': 'test3', 'name01': 'test2' },
{ 'name00': 'test4', 'name01': 'test5' },
{ 'name00': 'test5', 'name01': 'test4' }
]

# Desired result

results = [
{ 'name00': 'test1', 'name01': 'test2' },
{ 'name00': 'test1', 'name01': 'test3' },
{ 'name00': 'test4', 'name01': 'test5' }
]

【问题讨论】:

  • 这不是很清楚。您是否保证将包括所有n! 可能性?如果不是,删除组合的必要条件是什么,就像您对 2-3 所做的那样。如果集群是 1234,那么期望的输出是什么?
  • 为什么要以 dict 格式处理?我认为简单的解决方案是制作一组集群闭包,然后从中简单地生成 MST(最小生成树)。
  • @Prune 如果它是 1234 的所有组合,那么所需的输出是 12、13、14 不幸的是,我只是在处理脚本中传递的数据。我可以控制格式,但必须手动转换。
  • 我对完整性仍有疑问。例如,如果 7-8-9 是一个集群,我们会在给定的 dict 中拥有所有 6 对吗?
  • @Prune yes, 78, 79, 87, 89, 97, 98 结果应该是 78, 79 (或者 87, 89 或者 97, 98,哪个是真的没关系被选为“主要”)

标签: python python-2.7 list dictionary


【解决方案1】:

所有对都出现在列表中,实现应该足够简单。

对列表进行排序。 “较低”的标签将出现在前面。特别是,第一个条目将是一个可行的主要元素。将每个这样的链接放入结果列表,跟踪第二个元素。然后传递以“其他”名称开头的链接。重复此操作,直到您覆盖了整个原始列表。这是一个非常详细的版本:

start = [
    { 'name00': 'test1', 'name01': 'test2' },
    { 'name00': 'test1', 'name01': 'test3' },
    { 'name00': 'test2', 'name01': 'test1' },
    { 'name00': 'test2', 'name01': 'test3' },
    { 'name00': 'test3', 'name01': 'test1' },
    { 'name00': 'test3', 'name01': 'test2' },
    { 'name00': 'test4', 'name01': 'test5' },
    { 'name00': 'test5', 'name01': 'test4' }
]

result = []

start.sort(key=lambda link: link["name00"]+link["name01"]) 

for link in start:
    print(link)

link_key = None
pos = 0
while pos < len(start):

    other_name = []

    link = start[pos]
    if not link_key:
        link_key = link['name00']

    # Gather all of the links that start with the lowest name.
    # Keep track of the other names for later use.
    while start[pos]['name00'] == link_key:
        link = start[pos]
        result.append(link)
        other_name.append(link["name01"])
        pos += 1

    # Now is "later" ... ignore all links that start with other names.
    while pos < len(start) and              \
          start[pos]['name00'] in other_name:
        link = start[pos]
        pos += 1

    link_key = None


# Print the resulting pairs
for link in result:
    print(link["name00"], link["name01"])

输出:

test1 test2
test1 test3
test4 test5

【讨论】:

    【解决方案2】:

    不确定,但这是我的理解:

    results 中的两个项目 ij 被认为是相等的,如果:

    • i['name00'] == j['name00']i['name01'] == j['name01'])或
    • i['name01'] == j['name00']i['name00'] == j['name01'])。

    对吗?

    在这种情况下,您可以定义一个键,通过排序比较值“name00”/“name01”,然后使用该键将所有项目存储在字典中以消除重复项。

    例如:

    def key(item):
        return frozenset([item['name00'], item['name01']])
    
    
    by_key = {key(item): item for item in results}
    
    pprint.pprint(sorted(by_key.values()))
    

    你得到:

    [{'name00': 'test2', 'name01': 'test1'},
     {'name00': 'test3', 'name01': 'test1'},
     {'name00': 'test3', 'name01': 'test2'},
     {'name00': 'test5', 'name01': 'test4'}]
    

    【讨论】:

    • 是的,没错,但结果中还有额外的 3-2。
    • @OndřejŠevčík,你能进一步解释一下吗?我不明白为什么。
    • @LaurentLAPORTE 因为我将此数据传递给我无法更改的可视化脚本,如果它在其中,它会使可视化错误。
    猜你喜欢
    • 1970-01-01
    • 2017-07-21
    • 1970-01-01
    • 1970-01-01
    • 2021-04-17
    • 2017-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多