Python 在不重复记录键的情况下获取最大对数

Python 在不重复记录键的情况下获取最大对数,python,Python,我正在努力获得列表的最大利用率(“配对”) 我有一个字典列表,只要给定的k2不匹配,我就希望获得最大数量的“pare”。我猜是某种排列,缩小了资源列表 这就是我得到的: t = [ {'k1': 1, 'k2': 'a'}, {'k1': 2, 'k2': 'a'}, {'k1': 3, 'k2': 'b'}, {'k1': 4, 'k2': 'b'}, {'k1': 5, 'k2': 'c'}, {'k1': 6, 'k2': 'd'

我正在努力获得列表的最大利用率(“配对”

我有一个字典列表,只要给定的k2不匹配,我就希望获得最大数量的“pare”。我猜是某种排列,缩小了资源列表

这就是我得到的:

t = [ {'k1': 1, 'k2': 'a'},
      {'k1': 2, 'k2': 'a'},
      {'k1': 3, 'k2': 'b'},
      {'k1': 4, 'k2': 'b'},
      {'k1': 5, 'k2': 'c'},
      {'k1': 6, 'k2': 'd'},
      {'k1': 7, 'k2': 'a'},
      {'k1': 8, 'k2': 'd'}]

t2 = t[:]

for d in t2:
    for x in t2:
        if d['k2'] != x['k2']:
            print(d,x)
            t2.remove(x)
            t2.remove(d)
            break
问题是我剩下的是
t2=[{'k2':'d','k1':6},{'k2':'d','k1':8}]

这是一个浪费1对手动我可以实现以下目标:

({'k2': 'a', 'k1': 1}, {'k2': 'b', 'k1': 3})
({'k2': 'b', 'k1': 4}, {'k2': 'a', 'k1': 2})
({'k2': 'd', 'k1': 6}, {'k2': 'c', 'k1': 5})
({'k2': 'a', 'k1': 7}, {'k2': 'd', 'k1': 8})
或与之类似,共4对。我错过了一个技巧吗

更新

我需要的是,每次创建一对时,我都需要从列表中删除项目,因此我只能手动获得4个项目

我不关心巴黎,只要k2不匹配,并且我已经获得了最有效的配对列表,即在我上面的代码中,我浪费了一个可能的配对,因为没有使用字典与k2:d,因此这不是最有效的组合


如果仍然不清楚,我表示歉意,也许我的表述是错误的。

为了获得最大数量的可能对,您必须以智能方式创建对。考虑这样的输入:

k2_values = ['a', 'c', 'b', 'b']
如果您不想正确构建配对,则可能会将
a
c
配对,这将阻止您创建第二对,因为您只剩下2对
b
。要获得最大的对数,您必须开始使用您拥有最多的值构建对-使用
b

因此,第一步是根据
k2
值对DICT列表进行分组:

{'a': [{'k1': 1, 'k2': 'a'}, {'k1': 2, 'k2': 'a'}, {'k1': 7, 'k2': 'a'}],
 'b': [{'k1': 3, 'k2': 'b'}, {'k1': 4, 'k2': 'b'}],
 'c': [{'k1': 5, 'k2': 'c'}],
 'd': [{'k1': 6, 'k2': 'd'}, {'k1': 8, 'k2': 'd'}]}
然后按长度对这些组进行排序:

[[{'k1': 1, 'k2': 'a'}, {'k1': 2, 'k2': 'a'}, {'k1': 7, 'k2': 'a'}],
 [{'k1': 3, 'k2': 'b'}, {'k1': 4, 'k2': 'b'}],
 [{'k1': 6, 'k2': 'd'}, {'k1': 8, 'k2': 'd'}],
 [{'k1': 5, 'k2': 'c'}]]
最后从这些组中构建配对


实施 试运行:

>>> list(make_pairs(t, 'k2'))
[({'k1': 3, 'k2': 'b'}, {'k1': 1, 'k2': 'a'}),
 ({'k1': 4, 'k2': 'b'}, {'k1': 2, 'k2': 'a'}),
 ({'k1': 7, 'k2': 'a'}, {'k1': 6, 'k2': 'd'}),
 ({'k1': 8, 'k2': 'd'}, {'k1': 5, 'k2': 'c'})]

虽然我不完全确定,但这有一种。根据某种定义,您的箱子可以容纳2个具有唯一价值的物品。问题陈述是尽量减少使用过的箱子数量,或者换句话说,如果可能的话,避免生产只包含一个物品的箱子

实现近似解决方案相当简单。它不会为所有值产生完美的结果,但碰巧它确实为您的值找到了最佳解决方案:

def pairs(t, key):
    bins = []
    full = []

    for d in t:
        for i, (k, p) in enumerate(bins):
            if d[key] != k:
                p.append(d)
                full.append(p)
                # This is okay only because we do not continue
                # iterating after mutation.
                del bins[i]
                break

        else:
            # No bin could hold this d, so create a new one
            bins.append((d[key], [d]))

    return full
作为一种额外的测量方法,您可以先按频率对值进行排序,使其成为一种先拟合后下降的方法:

def pairs(t, key):
    lookup = defaultdict(list)

    for d in t:
        lookup[d[key]].append(d)

    gs = sorted(lookup.values(), key=len, reverse=True)
    ds = [d for g in gs for d in g]

    bins = []
    full = []

    for d in ds:
        ...

    ...

请提供您的预期输出。我只需要知道,从给定的dict列表中,我可以得到x对数。i、 在上面的例子中,我可以得到4对(手动)。唯一的要求是k2在“对”中不重复。输出可以是一个元组或一个列表,即
({'k2':'a','k1':7},{'k2':'b','k1':3})
,我将更新问题,那么为什么
(d,a)
不是一个有效的对呢?或者
(b,c)
?这里有4种以上的组合。你的问题很模糊。@Aran Fey,是的,我知道,但我不“在乎”关于巴黎,只要
k2
不匹配,并且我已经获得了最有效的配对列表,即在我上面的代码中,我浪费了1个可能的配对,因为我没有使用
k2:d
字典。顺便说一句,对你迭代的集合进行变异通常不是一个好主意。我喜欢这两个答案(第一个)一个是你在解释所有的步骤,另一个是简短的(最后一个),因为它更为压缩,虽然对我来说更难理解,因为我在python方面没有那么先进。我猜
iters=[(len(group),iter(group)]对于分组的组[u dicts]
这是列表竞争?在最后一个答案中,我不得不使用
表示zip中的l(itr1,itr2):产生l
,因为我使用的是python2,但这不是问题;)无论如何,你介意把你的答案的两个版本都放进去吗,因为下一个人可能会发现它同样有用;)@嗯,我宁愿不要。它太过嵌套和不直观,通常不是很好的代码。但我至少可以留下一个链接,以防有人真的想看。
def pairs(t, key):
    lookup = defaultdict(list)

    for d in t:
        lookup[d[key]].append(d)

    gs = sorted(lookup.values(), key=len, reverse=True)
    ds = [d for g in gs for d in g]

    bins = []
    full = []

    for d in ds:
        ...

    ...