2015-06-01 2 views
4

Я пытаюсь перевернуть словарь с помощью цикла for, чтобы отображать ключи и значения в порядке одного из элементов значения (номер заказа ватин).Зацикливание словаря для отображения ключа и значений в порядке значения

Я могу распечатать ключи и значения в указанном формате, но я не могу понять, как получить строки в правильном порядке ватин.

Мне нужно выполнить эту задачу с помощью логики в цикле for и без использования лямбда или функции. Вот то, что я до сих пор:

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 

Мой выход делает на самом деле выглядят так же, как это, за исключением порядка ватин будучи из строя , Пожалуйста, помогите мне подняться на правильный путь и помните, что я пытаюсь научиться здесь, поэтому любая полезная критика приветствуется!

+0

dicts неупорядоченны –

+0

@Padraic Да я знаю, что, но печать содержимого в определенном порядке возможно, и я пытаюсь научиться правильно это делать. – Wes

+0

Вы имеете в виду сортировку значений по ключу? Или, возможно, получить их в том порядке, в котором они были помещены в словарь? – Shashank

ответ

4

Вот эффективный способ, так как мы знаем, что будет 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 элементов и используя порядок ватина, чтобы сопоставить игрок и статистику в виде кортежа на правильный индекс массива. Затем мы перебираем массив игровых и статистических кортежей и печатаем желаемый отформатированный вывод. Это O (n).

Эта концепция в основном происходит от Radix sort, или, более конкретно, очень простой случай Counting sort где все ЧАСТОТЫ 1 и «функциональная клавиша» просто вычитанием 1 из моргнув порядке, чтобы получить индекс массива.

Как отмечает @PadraicCunningham в комментариях, это теоретически можно использовать для любого количества колодцев, используя функцию len.

+0

Мне очень нравится этот ответ, в настоящее время я пытаюсь прочитать его и убедиться, что полностью понимаю, как это работает. – Wes

+1

Вам не нужно жестко указывать количество колотит, вы можете '[Нет] * len (rays_starters)' –

+1

@PadraicCunningham Да, хороший момент! :) – Shashank

2

В словарях нет заказа, поэтому вы не можете отсортировать их. Однако вы можете перебирать значения in a sorted manner. Для этого вы можете использовать sorted() и ключевую функцию, которая определяет, как получить значение, когда прошло (key, value) кортеж:

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_starters словаря, то это даст следующий результат:

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 список, используя список понимание:

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

OP не может использовать лямбда или функцию –

+0

Это, конечно, правильный ответ, но, к сожалению, я уже знаю, как это сделать. Мне нужно попытаться выяснить, как это сделать без лямбды. – Wes

+0

@poke Прошу прощения, потому что я не полностью прочитал ваш ответ, увидев лямбду наверху. Вторым решением на самом деле может быть именно то, что я завязываю! – Wes

1

Похоже, лучший способ справиться с этим было бы (отсортированный) список 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)) 
+0

Вы можете вырезать 'lambda', используемый как ключ' sort', просто перечислив всех ваших игроков в соответствии с пониманием списка игроков. В качестве альтернативы вы можете использовать 'operator.attrgetter ('order')' –

+0

Жирная часть вопроса гласит, что lambdas и функции не могут использоваться. Странно, я знаю – Shashank

+0

@Shashank Я рассмотрел эту озабоченность в своем комментарии выше. «Лямбда» в этом коде просто не позволяет мне разобрать его список игроков вручную! : P –

2

Если вы не можете использовать мин, лямбды, сортируют и другие вызовы функций и т.д. вручную найти игрока с наименьшим номером игры ватин, начиная с самых низких:

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)) 

Выход:

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] 

Или без копирования:

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)) 

Если вы можете на самом деле сортировки или используйте сортировку, используйте номер ватин в качестве ключа и просто сортируйте позиции:

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

for k ,v in sorted(temp.items()): 
    print("{} {}".format(v[0], v[1:])) 

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] 

Если ватин всегда начинается с 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)) 

Выход:

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 
+0

Похоже, у него есть обещание для того, что я пытаюсь сделать. Мне нужно несколько минут, чтобы попытаться переварить. – Wes

2

Довольно просто и довольно ineficcient способ сделать это итерация len (rays_starters) раз по массиву и только печать результата, который каждый раз соответствует порядку.

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]) 
0

Я опоздал на вечеринку, но я хочу добавить это взломать все равно:

>>> 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

Смежные вопросы