Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
基于2个类属性的Python排序_Python_Sorting - Fatal编程技术网

基于2个类属性的Python排序

基于2个类属性的Python排序,python,sorting,Python,Sorting,编辑:刚刚发现我使用的是py 2.6.2(安装了工作,所以我对此无能为力) 因此,我试图找到根据两个不同的类属性对列表进行排序的最佳方法 该列表基本上是一些信息,用于在一家公司内将人员从一个房间移动到另一个房间,其中一些人可能是连锁移动的一部分 (也就是说,乔·布鲁必须在我们将简·多伊转移到乔的位置之前移动,简必须在约翰·威克转移到简的位置之前移动,等等) 我得到了如下所示的所有信息,但也可能有一些人不属于链的一部分,比如下面示例中的Dan Man John Wick 303.10 ->

编辑:刚刚发现我使用的是py 2.6.2(安装了工作,所以我对此无能为力)

因此,我试图找到根据两个不同的类属性对列表进行排序的最佳方法

该列表基本上是一些信息,用于在一家公司内将人员从一个房间移动到另一个房间,其中一些人可能是连锁移动的一部分 (也就是说,乔·布鲁必须在我们将简·多伊转移到乔的位置之前移动,简必须在约翰·威克转移到简的位置之前移动,等等)

我得到了如下所示的所有信息,但也可能有一些人不属于链的一部分,比如下面示例中的Dan Man

John Wick 303.10 -> 415.09
Dan Man 409.08 -> 221.02
Joe Blow 225.06 -> 512.01
Jane Doe 415.09 -> 225.06
我将所有相关信息拆分为一个类

startRoom
endRoom
originalString
所以这一部分不是问题,但当我尝试“暴力”排序时,如下所示:(注意,我做列表(链),因为它以前是一个集合,以确保我不会在其中得到双倍)

我的问题是分类。问题的一部分是找到位于链起点的人,然后正确排序。
非常感谢您的任何想法/帮助。是的,我知道在循环中移动东西时出现双循环不是最好的,但这是当时我能想到的最好的方法。

首先,你必须创建一个依赖关系图,并确定(a)在其他人可以移动之前,哪些人必须移动
,以及(b)哪些人现在可以移动。我们可以在这里使用1:1映射,但在更一般的情况下,可能必须使用1:n、n:1或n:m映射

moves = {"John Wick": ("303.10", "415.09"),
         "Dan Man":   ("409.08", "221.02"),
         "Joe Blow":  ("225.06", "512.01"),
         "Jane Doe":  ("415.09", "225.06")}
# or dict((move.originalString, (move.startRoom, move.endRoom)) for move in list_of_moves)

# mapping {initial room -> name}
rooms = {start: name for (name, (start, end)) in moves.items()}
# Python 2.6: dict((start, name) for (name, (start, end)) in moves.items())

# mapping {moves_first: moves_after}
before = {rooms[end]: name for name, (start, end) in moves.items() if end in rooms}
# Python 2.6: dict((rooms[end], name) for name, (start, end) in moves.items() if end in rooms)

# persons that can move now
can_move = set(moves) - set(before.values())
现在,我们可以看到谁可以移动,移动那个人,然后根据那个人需要等待什么来更新可以移动的人,如果有的话

result = []
while can_move:
    # get person that can move, add to result
    name = can_move.pop()
    result.append(name)
    # add next to can_move set
    if name in before:
        can_move.add(before.pop(name))
之后,
结果是
['Joe Blow'、'Jane Doe'、'John Wick'、'Dan Man']


复杂性应该是O(n),但当然,如果存在循环依赖,这将失败。

您将如何排序
[(A,1,2),(B,2,1)]
?链是否需要保持分组?或者在你的例子中输出
Joe->Dan->Jane->John
可以吗?@adrio会很好,因为我有另一个循环要通过,并在链之间添加一个间隔(因为可能有多个)你能确保:1)所有给定的移动都是可行的(即没有两个具有相同值的尾端空间)2)没有循环移动吗(例如,A移动到B的位置,B移动到C的位置,C移动到A的位置)对于任何数量的人,考虑到如果人A从A移动到B,然后从B移动到C,并且人B从d移动到B,这不符合1)。但是,这仍然是一个有效的移动,因为a将在c中结束,B将在B中结束。对于您和Tobias的房间={start:name For(name,(start,end))in moves.items()}会在For处导致无效语法keyword@TEvashkevich然后,您使用的是非常旧的Python版本,可能是2.6或更旧的版本。查看我的编辑。你能添加几行吗?这与我的版本有什么不同/更好的地方吗?@tobias_k刚刚检查过,你是对的。它显然是2.6.2(我以为我使用的是更新的版本,但不幸的是不是我的决定)@tobias_k我刚才在我简单复制的第一行中提到了你。其余部分明显不同。编辑后肯定更接近。现在说这个列表并没有属性,我只是试着用枚举(移动)来代替,但说的是TypeError:iteration over non sequence。如果我只是删除.items也是一样的错误…所以关闭编辑:另外,为了澄清,上面代码中的开始/结束应该是我的startRoom/endRoom正确吗?@TEvashkevich
键入(移动)
说什么?它应该是一个
目录
,而不是
列表
。您是否定义了一个函数
dict
,隐藏了
dict
bultin函数?啊,我把它列为一个列表,因为我的东西只是从一个txt文件中读取的,我把它放在了我前面提到的类中。我想我可以重新写一封信,把它扔进一个dict@TEvashkevich查看另一个编辑,了解如何从
Move
对象列表创建dict。哦,很好,我不知道你可以这样做只是为了制作一本字典!谢谢你,老兄,你完全解决了我的难题
def do(moves):
    """RETURNS: [0] Sequence of persons to move.
                [1] Remainder
    """
    # (following line copied from 'tobias_k', replaced 'rooms' with 'current_db')
    # map: target position to person who occupies it
    current_db = { start: name for (name, (start, end)) in moves.items() }
    # maintain set of persons who are free to move to their target location
    liberated_set = set()
    # map occupier of a location -> set of people who would take his place.
    liberation_db = defaultdict(set)
    # whosoever wants to move to a free place -> liberated.
    # else                                    -> liberation_db
    for name, (start, end) in moves.items():
        occupier = current_db.get(start)
        if occupier is None: liberated_set.add(name)
        else:                liberation_db[occupier].add(name)

    sequence = []
    while liberated_set:
        # add people to the sequence who are free to move
        sequence.extend(liberated_set)
        # get new set of people who are free to move to their target
        # because their target position is no longer occupied.
        new_liberated_set = set()
        for occupier in liberated_set:
            if not occupier in liberation_db: continue
            new_liberated_set.extend(liberation_db[occupier])
            del liberation_db[occupier]
        liberated_set = new_liberated_set

     return sequence, set(liberation_db.values())
def do(moves):
    """RETURNS: [0] Sequence of persons to move.
                [1] Remainder
    """
    # (following line copied from 'tobias_k', replaced 'rooms' with 'current_db')
    # map: target position to person who occupies it
    current_db = { start: name for (name, (start, end)) in moves.items() }
    # maintain set of persons who are free to move to their target location
    liberated_set = set()
    # map occupier of a location -> set of people who would take his place.
    liberation_db = defaultdict(set)
    # whosoever wants to move to a free place -> liberated.
    # else                                    -> liberation_db
    for name, (start, end) in moves.items():
        occupier = current_db.get(start)
        if occupier is None: liberated_set.add(name)
        else:                liberation_db[occupier].add(name)

    sequence = []
    while liberated_set:
        # add people to the sequence who are free to move
        sequence.extend(liberated_set)
        # get new set of people who are free to move to their target
        # because their target position is no longer occupied.
        new_liberated_set = set()
        for occupier in liberated_set:
            if not occupier in liberation_db: continue
            new_liberated_set.extend(liberation_db[occupier])
            del liberation_db[occupier]
        liberated_set = new_liberated_set

     return sequence, set(liberation_db.values())