编辑:刚刚发现我正在使用py 2.6.2(已安装工作,因此我无法做太多)
所以我试图找到基于2个不同类属性对列表进行排序的最佳方法
这个列表基本上是一些信息,用于在一家公司中将人们从一个房间移动到另一个房间,在这个公 (即Joe Blow在我们将Jane Doe移动到Joe的位置之前必须移动而Jane必须在John Wick移动到Jane的位置之前移动。)
我得到的信息如下所示,但在下面的示例中,也可能有人像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
所以那个部分不是问题但是当我尝试“暴力”时将其排序如下:(注意,我做列表(链),因为它以前是一套,以确保我没有得到双打在那里)
def sortChains():
global chains
#convert the set of chains to a list for list functions
chains = list(chains)
for x, move1 in enumerate(chains):
for y, move2 in enumerate(chains):
if move1.startRoom == move2.endRoom:
temp = chains[y]
chains.remove(move2)
chains.insert(x,temp)
continue
我的问题是排序。问题的一部分是找到链条起点的人员,然后在此之后正确排序。 任何想法/帮助是完全赞赏的。是的,我知道一个双循环,而在循环中移动东西不是最好的,但它是我当时想到的最好的。
答案 0 :(得分:2)
首先,你必须创建一个依赖图并确定(a)哪个人必须移动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())
其他人可以移动,以及(b)哪些人现在可以移动。我们可以在这里使用1:1映射,但在更一般的情况下,您可能必须使用1:n,n:1或n:m映射。
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))
现在,我们可以看到谁可以移动,移动那个人,然后根据必须等待该人移动的人(如果有的话)更新可以移动的人。
result
之后,['Joe Blow', 'Jane Doe', 'John Wick', 'Dan Man']
为{{1}}
复杂性应该是O(n),但当然,如果存在循环依赖性,这将失败。
答案 1 :(得分:0)
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())