4

我有以下类型的列表:

class Ind(object):
    def __init__(self,ID,mate):
        self.ID=ID
        self.mate=mate

population=[Ind(8,None), Ind(1,2), Ind(20,3), Ind(2,1), Ind(12,None), Ind(3,20), Ind(10,11), Ind(11,10)]

您可以将此列表population视为拥有ID. 他们中的一些人有一个mate(存在于同一人群或同一列表中的个人)。mate价值实际上是ID伴侣的!因此,如果存在Ind其属性等​​于ID12 且mate等于 34 的实例,则列表中必然存在一个其ID等于 34 且其等于 12 的个体。属性中mate没有 have 的mate个体Nonemate是否有意义?

我想对这个列表进行排序,以便第一个个体与最后一个个体配对,第二个个体与倒数第二个个体配对,等等......属性mate等于的个体None应该站在列表的中间。

有许多可能的输出适合我想要的。以下是上述列表的这些输出的一个示例:

population=[Ind(1,2), Ind(20,3), Ind(10,11), Ind(8,None), Ind(12,None), Ind(11,10), Ind(3,20), Ind(2,1)]
4

4 回答 4

5

你可以尝试这样的事情:

def custom_sort(population):
    pop_dict = { ind.ID: ind for ind in population }

    start = []
    nones = []
    end = []
    for ind in population:
        if ind.mate is None:
            nones.append(ind)
        elif pop_dict[ind.mate] not in start:
            start.insert(0, ind)
            end.append(pop_dict[ind.mate])
    return start + nones + end

这是假设“成为伴侣”是一对一的关系。

于 2013-08-26T15:29:21.930 回答
2

您只需要一个用于排序功能的键。以下示例要求个人是一夫一妻制的,并且不与自己结婚。它还要求如果 (a,b) 被列出,则 (b,a) 也被列出。如果不满足这些先决条件并且 Ind(2,1) 可以在没有 Ind(1,2) 的情况下发生,则此函数会将 Ind(2,1) 放在列表的末尾。关键函数中的第一个索引是类型:关系中的“第一”(其中 IDmate)排在第三位。这些第一种和第二种类型按它们的 id 排序;最后一种类型按其配对以相反的顺序排序。

def keyfun(x):
   if x.mate==None: 
     return (1,x.ID)
   elif x.ID<x.mate: 
     return (0,x.ID)
   else:
     return (2,-x.mate)

sorted(population,key=keyfun)

另一种处理这个问题的方法,仍然假设如果 (a,b) 在列表中 (b,a) 也将在列表中,只是通过删除 (b,a) 案例进行预处理,然后通过添加它们来进行后处理以相反的顺序。

于 2013-08-26T16:01:27.950 回答
0

这个怎么样。将列表拆分为三个列表,一个带有ID < mate,第二个带有ID > mate,第三个带有mate is None。然后,连接排序列表,每个列表都通过 ID 排序。

我在类中添加了一个__repr__方法以Ind提高输出的可读性。

class Ind(object):
    def __init__(self,ID,mate):
        self.ID=ID
        self.mate=mate

    def __repr__(self):
        return 'Ind({},{})'.format(self.ID,self.mate)

population=[Ind(8,None), Ind(1,2), Ind(2,3), Ind(2,1), Ind(12,None), Ind(3,2), Ind(10,11), Ind(11,10)]

def custom_sort(pop):
    singles, less, more = [], [], []
    for p in pop:
        if p.mate is None:
            singles.append(p)
        elif p.ID < p.mate:
            less.append(p)
        elif p.ID > p.mate:
            more.append(p)
    comp = lambda x,y: cmp(x.ID,y.ID)
    return sorted(less,cmp=comp) + sorted(singles,cmp=comp) + sorted(more,cmp=comp,reverse=True)


print custom_sort(population)

这输出:

[Ind(1,2), Ind(2,3), Ind(10,11), Ind(8,None), Ind(12,None), Ind(11,10), Ind(3,2), Ind(2,1)]
于 2013-08-26T15:51:11.980 回答
0

您可以使用 costum 键功能做很多事情:

def my_key(ind):
    if ind.mate is None:
        return 0
    if ind.ID < ind.mate:
        return -ind.ID - 1
    else:
        return ind.mate + 1
population.sort(key=my_key)

这假设 ID 永远不会是负数。如果 ID 始终大于 0,则可以丢弃- 1+ 1

于 2013-08-26T16:02:00.493 回答