Python 在字典上循环以按值的顺序显示键和值

Python 在字典上循环以按值的顺序显示键和值,python,dictionary,Python,Dictionary,我试图在字典上循环使用for循环,以按值元素之一(击球顺序号)的顺序显示键和值 我可以按预定格式打印键和值,但我不知道如何以正确的击球顺序打印线 我需要使用for循环中的逻辑来完成此任务,并且不需要使用lambda或函数。以下是我目前所拥有的: print ('Rays starters' + "\n") rays_starters = { 'DeJesus' : ['DH', 6, 299], 'Loney' : ['1B', 4, 222], 'Rivera' : [

我试图在字典上循环使用
for
循环,以按值元素之一(击球顺序号)的顺序显示键和值

我可以按预定格式打印键和值,但我不知道如何以正确的击球顺序打印线

我需要使用for循环中的逻辑来完成此任务,并且不需要使用lambda或函数。以下是我目前所拥有的:

print ('Rays starters' + "\n")
rays_starters = {
    'DeJesus' : ['DH', 6, 299],
    'Loney' : ['1B', 4, 222],
    'Rivera' : ['C', 9, 194],
    'Forsythe' : ['2B', 5, 304],
    'Souza Jr' : ['RF', 2, 229],
    'Longoria' : ['3B', 3, 282],
    'Cabrera' : ['SS', 7, 214],
    'Kiermaier' : ['CF', 1, 240],
    'Guyer' : ['LF', 8, 274] }
for player in rays_starters:
    print (player + str(rays_starters[player]))
print ('\n' + 'Today\'s lineup' + '\n')
for player in rays_starters:
    batting_order = rays_starters.get(player)
    print('Batting ' + str(batting_order[1]) + ' : ' + str(batting_order[0]) + ' ' + player + ' ,current avg: ' + str(batting_order[2]))   
输出应如下所示:

Rays starters

DeJesus ['DH', 6, 299]
Loney ['1B', 4, 222]
Rivera ['C', 9, 194]
Forsythe ['2B', 5, 304]
Souza Jr ['RF', 2, 229]
Longoria ['3B', 3, 282]
Cabrera ['SS', 7, 214]
Kiermaier ['CF', 1, 240]
Guyer ['LF', 8, 274]

Today's lineup

Batting 1 : CF Kiermaier ,current avg: 240
Batting 2 : RF Souza Jr ,current avg: 229
Batting 3 : 3B Longoria ,current avg: 282
Batting 4 : 1B Loney ,current avg: 222
Batting 5 : 2B Forsythe ,current avg: 304
Batting 6 : DH DeJesus ,current avg: 299
Batting 7 : SS Cabrera ,current avg: 214
Batting 8 : LF Guyer ,current avg: 274
Batting 9 : C Rivera ,current avg: 194

事实上,我的输出与此一模一样,只是击球顺序有问题。请帮助我走上正确的道路,记住我正在努力学习,所以欢迎任何有用的批评

字典没有顺序,因此无法对其进行排序。但是,您可以对其值进行迭代。为此,可以使用
sorted()
和一个键函数,该函数指定在传递
(键,值)
元组时如何获取值:

for player, batting in sorted(rays_starters.items(), key=lambda x: x[1][1]):
    print('Batting {1} : {0} {player}, current avg: {2}'.format(*batting, player=player))
对于
rays\u初学者
字典,这将产生以下结果:

Batting 1 : CF Kiermaier, current avg: 240
Batting 2 : RF Souza Jr, current avg: 229
Batting 3 : 3B Longoria, current avg: 282
Batting 4 : 1B Loney, current avg: 222
Batting 5 : 2B Forsythe, current avg: 304
Batting 6 : DH DeJesus, current avg: 299
Batting 7 : SS Cabrera, current avg: 214
Batting 8 : LF Guyer, current avg: 274
Batting 9 : C Rivera, current avg: 194
如果不能指定这样的键函数,则必须自己实现排序。为此,您可以首先将字典转换为列表,然后进行排序。为了不需要键函数,您应该构造该列表,以便要排序的值位于列表的第一位:

data = []
for player, batting in rays_starters.items():
    data.append((batting[1], player, batting[0], batting[2]))

# now sort the list
data.sort()

# and iterate and print
for player in data:
    print('Batting {0} : {1} {2}, current avg: {3}'.format(*player))
您还可以使用列表理解创建
数据
列表:

data = [(b[1], p, b[0], b[2]) for p, b in rays_starters.items()]

似乎更好的处理方法是(排序)列出
namedtuples

from collections import namedtuple

Player = namedtuple("Player", ['name', 'position', 'order', 'avg'])
players = [Player(*info) for info in [("DeJesus", "DH", 6, 299),
                                      ('Loney', '1B', 4, 222),
                                      ...]]

players.sort(key=lambda p: p.order)

for player in players:
    print("Batting {p.order} : {p.position} {p.name}, current avg {p.avg}".format(p=p))

如果无法使用min、lambdas、sorted和其他函数调用等手动查找击球数最低的球员,从最低开始:

out = []
cp = rays_starters.copy()
# keep going while the dict is not empty
while cp:
    mn = float("inf")
    it = None
    # iterate over the item to find the min each time
    # from remaining items
    for k, v in cp.items():
        if v[1] < mn:
            mn = v[1]
            it = (k, v)
    # append current it k/v pair which has the lowest 
    # batting number         
    out.append(it)
    # remove the key so we can get the next lowest
    del cp[it[0]]

for k,v in out:
    print("{} {}".format(k,v))
或不复制:

out = []
seen = set()
# for every player in the dict
for _ in rays_starters):
    mn = float("inf")
    it = None
    # again get min each time based on the batting number
    for k, v in rays_starters.items():
        # this time we make sure we have not already used
        # the player 
        if v[1] < mn and k not in seen:
            mn = v[1]
            it = (k, v)
    out.append(it)
    # add the name of the player that matches our current min
    seen.add(it[0])

for k,v in out:
    print("{} {}".format(k,v))
如果击球总是从1开始:

temp = {v[1]:[k]+v for k, v in rays_starters.items()}

for k  in range(1,len(rays_starters)+1):
    v = temp[k]
    print("{} {}".format(v[0], list(v[1:])))
您可以解压缩以打印:

temp = {v[1]:[k]+v for k, v in rays_starters.items()}

for k in range(1,len(rays_starters)+1):
    name, nm, btn, avg = temp[k]
    print("Batting: {} {} {}, current avg: {}".format(btn, name, nm, avg))
输出:

Kiermaier ['CF', 1, 240]
Souza Jr ['RF', 2, 229]
Longoria ['3B', 3, 282]
Loney ['1B', 4, 222]
Forsythe ['2B', 5, 304]
DeJesus ['DH', 6, 299]
Cabrera ['SS', 7, 214]
Guyer ['LF', 8, 274]
Rivera ['C', 9, 194]
Batting: 1 Kiermaier CF, current avg: 240
Batting: 2 Souza Jr RF, current avg: 229
Batting: 3 Longoria 3B, current avg: 282
Batting: 4 Loney 1B, current avg: 222
Batting: 5 Forsythe 2B, current avg: 304
Batting: 6 DeJesus DH, current avg: 299
Batting: 7 Cabrera SS, current avg: 214
Batting: 8 Guyer LF, current avg: 274
Batting: 9 Rivera C, current avg: 194

一种非常简单也非常无效的方法是在数组上迭代len(rays_start)次,每次只打印与顺序匹配的结果

for i in range (1, len(rays_starters)+1):
    for player in rays_starters:
        if rays_starters[player][1] == i:
            print('Batting ' + str(rays_starters[player][1]) + ' : ' + \
            rays_starters[player][1] + ' ' + player + ' ,current avg: ' + \
            rays_starters[player][1])

这是一个有效的方法,因为我们知道将有9名击球手

lineup = [None] * 9
for player, stats in rays_starters.items():
    lineup[stats[1]-1] = player, stats
print ('\nToday\'s lineup\n')
for player, batting_order in lineup:
    print('Batting ' + str(batting_order[1]) + ' : ' + str(batting_order[0]) + ' ' + player + ' ,current avg: ' + str(batting_order[2]))
我们所做的只是初始化一个包含9个元素的数组,并使用击球顺序将球员和统计数据作为元组映射到正确的数组索引。然后我们循环遍历player和statistics元组数组,并打印所需的格式化输出。这是O(n)

这个概念基本上来源于,或者更具体地说,一个非常简单的例子,其中所有频率都是1,“关键函数”只是从击球顺序中减去1,以获得一个数组索引


正如@PadraicCunningham在评论中指出的那样,理论上,通过使用
len
功能,这可以用于任何数量的击球手。

我参加派对迟到了,但我还是想添加这一技巧:

>>> for x in {v[1]:'Batting {2} : {1} {0} ,current avg: {3}'.format(k,*v)
              for k,v in rays_starters.items()}.values():
        print(x)

Batting 1 : CF Kiermaier ,current avg: 240
Batting 2 : RF Souza Jr ,current avg: 229
Batting 3 : 3B Longoria ,current avg: 282
Batting 4 : 1B Loney ,current avg: 222
Batting 5 : 2B Forsythe ,current avg: 304
Batting 6 : DH DeJesus ,current avg: 299
Batting 7 : SS Cabrera ,current avg: 214
Batting 8 : LF Guyer ,current avg: 274
Batting 9 : C Rivera ,current avg: 194
但不要这样做,它依赖于字典项的实际但不保证的顺序。我只是为了教育娱乐才贴的



另一方面,如果你删除一些播放器,它仍然有效,这与公认的答案不同:-p

@Padraic是的,我知道这一点,但以特定顺序打印内容是可能的,我正在尝试学习如何正确操作。你是指按键排序值吗?或者可能是按照它们放入字典的顺序检索它们?如果不使用需要lambda或使用itemgetter进行函数调用的键进行排序,那么您需要手动创建一个列表,按照您想要的顺序使用名称,在列表上迭代并执行以下操作:lookups@Shashank,输出基于击球顺序,r每个列表的第二个元素我的想法是应该有某种方法来访问值的第二个元素中的数字,即击球顺序,并将其与列表1-9进行比较以按该顺序打印,但我一直在绞尽脑汁试图确定如何执行。OP不能使用lambda或函数这当然是正确的回答,但不幸的是,我已经知道如何这样做。我需要试着找出没有lambda的情况下该怎么做。@我很抱歉,因为在看到lambda位于顶部后,我没有完全阅读您的答案。你的第二个解决方案可能正是我想做的@Wes没有必要道歉,因为我也错过了“没有lambda或功能”的要求;这就是为什么我在回答中添加了另一个解决方案;)只需在
players
列表中按顺序列出所有玩家,即可去掉用作
sort
键的
lambda
。或者,您可以使用
operator.attrgetter('order')
问题的粗体部分说明可能不使用lambda和函数。奇怪,我know@Shashank我在上面的评论中提到了这一关切。此代码中的
lambda
只是为了避免我不得不手工解析他的玩家列表!:帕尔虽然这对手头的任务没有多大帮助,但它确实有助于我理解lambda,因此感谢你的回答。@Adam我同意你的观点,但作为一名学生,我没有能力决定解决方案的参数,而是必须遵循作业规则。我只是把这当作“我的头要爆炸”的最后手段。在过去的几天里,我用了几种不同的方法解决了这个问题,包括使用lambda,这肯定是最简洁的方法,但解决教授想要解决的问题的方法被证明是非常难以捉摸的。这看起来对我正在尝试做的事情有希望。我需要一些时间来试着消化。我真的很喜欢这个答案,我目前正在努力阅读它,并确保我完全理解它是如何工作的。你不需要硬编码你可以
[None]*len(rays\u starters)
>>> for x in {v[1]:'Batting {2} : {1} {0} ,current avg: {3}'.format(k,*v)
              for k,v in rays_starters.items()}.values():
        print(x)

Batting 1 : CF Kiermaier ,current avg: 240
Batting 2 : RF Souza Jr ,current avg: 229
Batting 3 : 3B Longoria ,current avg: 282
Batting 4 : 1B Loney ,current avg: 222
Batting 5 : 2B Forsythe ,current avg: 304
Batting 6 : DH DeJesus ,current avg: 299
Batting 7 : SS Cabrera ,current avg: 214
Batting 8 : LF Guyer ,current avg: 274
Batting 9 : C Rivera ,current avg: 194