使用Python中的自定义比较函数对字典键对象列表进行排序

时间:2015-03-19 02:31:45

标签: python c++ dictionary

我将一些代码从C ++移植到Python,它依赖于使用自定义比较函数的地图中键的C ++排序。我假设我可以简单地使用Python字典,然后在键上使用sorted(),使用等效函数作为键=到sorted()。但是,无论我如何尝试,都会在Python中以不同的顺序遍历键。

C ++代码是我在gitub上找到的gSpan的一些随机实现here。请参阅src / gspan.h和src / graph.h中的ProjectionMap和struct dfs_code_t。

我的简化python代码如下,包括C ++代码中两个比较函数的直接副本:

dfs_code = collections.namedtuple('dfs_code',
            ['fromn','to','from_label','edge_label','to_label'])

def dfs_code_compare(a, b):
    if a.from_label != b.from_label:
        return a.from_label < b.from_label
    else:
        if a.edge_label != b.edge_label:
            return a.edge_label < b.edge_label
        else:
            return a.to_label < b.to_label

def dfs_code_backward_compare(a, b):
    if a.to != b.to:
        return a.to < b.to
    else:
        return a.edge_label < b.edge_label

# code that fills in a dictionary called pm

for pm in sorted(projection_map, key=functools.cmp_to_key(dfs_code_compare)):
        print pm

上面的python代码产生以下顺序:

dfs_code(fromn=0, to=1, from_label=1, edge_label=0, to_label=3)
dfs_code(fromn=0, to=1, from_label=2, edge_label=3, to_label=2)
dfs_code(fromn=0, to=1, from_label=1, edge_label=3, to_label=3)
dfs_code(fromn=0, to=1, from_label=1, edge_label=1, to_label=2)
dfs_code(fromn=0, to=1, from_label=2, edge_label=1, to_label=3)
....

哪个是a)与C ++代码不同,b)根本不是我对比较函数所期望的(我希望所有from_labels为1在前面组合在一起,例如)。有任何想法吗?它与functools.cmp_to_key有关吗?

1 个答案:

答案 0 :(得分:4)

在python中,比较函数必须返回负值,正值或零值,指示第一个元素是小于,大于还是等于第二个元素。因为python的&lt;运算符返回一个bool,你的问题来自python将False转换为0并假设这些值相等。

您可以重写比较函数以使用此约定,但可能更容易编写关键函数。

例如,dfs_code_compare可以转换为此键功能:

def dfs_code_key(pm):
    return (pm.from_label, pm.edge_label, pm.to_label)

并像这样使用:

for pm in sorted(projection_map, key=dfs_code_key):
    pm