在Python中按顺序排序字典

时间:2015-01-15 20:08:14

标签: python sorting dictionary

我正在尝试创建一个脚本,该脚本将获取唯一键的字典,并按类似列出的字符串值进行排序。每个值都按导入的csv的优先顺序列出。我是python的新手,在构思这个问题上遇到了一些麻烦,但到目前为止,我有一个类似的字典:

myDict = { 's1' : ['a', 'c', 'b', 'd'], 
           's2' : ['c', 'd', 'a', 'b'], 
           's3' : ['a', 'b', 'c', 'd'], 
           's4' : ['c', 'a', 'b', 'd'], 
           's5' : ['a', 'b', 'd', 'c'], 
           's6' : ['c', 'a', 'b', 'd'],
           's7' : ['b', 'a', 'a', 'd'],
           's8' : ['c', 'b', 'd', 'a']}

#next I created a new dictionary where the values are listed keys to be filled
newDict = { 'a' : [], 'b' : [], 'c': [], 'd' : [] }

#updating newDict by 1st listed value in myDict
for j in range(1):
    for x in myDict.keys():
        newDict[myDict[x][j]].append(x)

#result
newDict = { 'a' : ['s1', 's3', 's5'], 'b': ['s7'], 'c' : ['s2', 's4', 's6', 's8'], 'd': [] }

接下来,我想循环它引用myDict中列出的值并填入newDict键,以便每个键都有两个值,通过它们的“有序”首选项进行平衡。

这意味着它必须从myDict键引用第二个或第三个列出的值并更新其值以找到余额。例如:

#intended final newDict values
newDict = { 'a' : ['s1', 's5'], 'b': ['s7', 's3'], 'c' : ['s4', 's6'], 'd': ['s2', 's8'] }

对任何错误表示歉意并感谢您的见解

2 个答案:

答案 0 :(得分:1)

以下是您希望的结果的一种可能实现

myDict = { 's1' : ['a', 'c', 'b', 'd'], 
           's2' : ['c', 'd', 'a', 'b'], 
           's3' : ['a', 'b', 'c', 'd'], 
           's4' : ['c', 'a', 'b', 'd'], 
           's5' : ['a', 'b', 'd', 'c'], 
           's6' : ['c', 'a', 'b', 'd'],
           's7' : ['b', 'a', 'a', 'd'],
           's8' : ['c', 'b', 'd', 'a']}

options = ['a', 'b', 'c', 'd']
newDict = {option: [] for option in options}
for key, value in myDict.items():
    newDict[value[0]].append(key)

# balance out the dictionary
desired_length = 2
while True:
    for key, value in newDict.items():
        if len(value) > desired_length:
            popped = value.pop()
            new_index = myDict[popped].index(key) + 1
            new_key = myDict[popped][new_index]
            print('Move {} from {} to {}'.format(popped, key, new_key))
            newDict[new_key].append(popped)
    if all(len(value) == desired_length for value in newDict.values()):
        break
print(newDict)

输出:

Move s4 from c to a
Move s4 from a to b
Move s6 from c to a
Move s6 from a to b
Move s6 from b to d
Move s5 from a to b
Move s5 from b to d
{'d': ['s6', 's5'], 'b': ['s7', 's4'], 'c': ['s8', 's2'], 'a': ['s3', 's1']}

这在任何意义上都不是“最佳”(虽然我甚至不知道你会认为什么是最优的),也不能保证返回一个有用的结果(可以想象我们可以用完一个/ b /给定s#的c / d选项,从而走出列表的末尾),也不是确定性的(因为字典的迭代顺序可能因运行而异),但也许它会让你知道在哪里开始,你需要更好地了解你的目标。

答案 1 :(得分:0)

这是解决问题的一种简单方法,拒绝填充newDict中包含两个以上项目的列表。它可能不是最佳的,因为它奖励了第一选择"基于先到先得的基础,而不考虑哪些第二选择比其他选择更容易填充。然而,它确实首先考虑所有的第一名选秀权,然后是所有第二名选秀权,然后是第三名,等等。

from collections import defaultdict, deque

myDict = { 's1' : ['a', 'c', 'b', 'd'], 
           's2' : ['c', 'd', 'a', 'b'], 
           's3' : ['a', 'b', 'c', 'd'], 
           's4' : ['c', 'a', 'b', 'd'], 
           's5' : ['a', 'b', 'd', 'c'], 
           's6' : ['c', 'a', 'b', 'd'],
           's7' : ['b', 'a', 'a', 'd'],
           's8' : ['c', 'b', 'd', 'a']}

newDict = defaultdict(list)

to_assign = deque(myDict.items())          # Start with a queue of all of myDict's items
while to_assign:
    key, value = to_assign.popleft()       # Take an item off the queue
    if len(newDict[value[0]]) < 2:         # See if its first pick is available
        newDict[value[0]].append(key)      # If so, add it to the result
    else:                                  # Otherwise, put the item on the
        to_assign.append((key, value[1:])) # end of the queue with its first pick removed