简体   繁体   中英

Sorting a list of list of tuples based on the sum of first field in the tuple in Python

I have an outermost list which contains a monthly total count of different items in this format. Every month has the same items.

big_list = [
  [
    (20, 'Item A', 'Jan'),
    (30, 'Item B', 'Jan'),
    (12, 'Item C', 'Jan'),
  ],
  [
    (22, 'Item A', 'Feb'),
    (34, 'Item B', 'Feb'),
    (15, 'Item C', 'Feb'),
  ],

  .... # until 'Dec'
]

And I want to sort this list based on the total number of item counts throughout a year. (The sum of the first field in the tuple of a particular item throughout the year) . For instance, if Item C has the most counts in the two months followed by Item A and Item B , the end result would be

[
  [
    (12, 'Item C', 'Jan'),
    (20, 'Item A', 'Jan'),
    (30, 'Item B', 'Jan'),
  ],
  [
    (15, 'Item C', 'Feb'),
    (22, 'Item A', 'Feb'),
    (34, 'Item B', 'Feb'),
  ],

  ... # until 'Dec'
]
# Item C = 12 + 15 = 27
# Item A = 20 + 22 = 42
# Item B = 30 + 34 = 64

How can I achieve this? Any help or enlightenment would be much appreciated.

big_list = [
  [
    (20, 'Item A', 'Jan'),
    (30, 'Item B', 'Jan'),
    (12, 'Item C', 'Jan'),
  ],
  [
    (22, 'Item A', 'Feb'),
    (34, 'Item B', 'Feb'),
    (15, 'Item C', 'Feb'),
  ]]

s = {}
for l in big_list:
    for m in l:
        s[m[1]] = s.get(m[1], 0) + m[0]

gives us s - the sums we want to use to sort: {'Item A': 42, 'Item B': 64, 'Item C': 27}

And finally:

for l in big_list:
    l.sort(key=lambda x: s[x[1]])

changes big_list to:

[[(12, 'Item C', 'Jan'), (20, 'Item A', 'Jan'), (30, 'Item B', 'Jan')],
 [(15, 'Item C', 'Feb'), (22, 'Item A', 'Feb'), (34, 'Item B', 'Feb')]]

This solution works for lists within months in any order and also if some item does not appear in some month.

If you really need a two liner:

for small_list in big_list:
  small_list.sort(key=lambda x: -sum([y[0] for l in big_list for y in l  if y[1] == x[1]]))

edit: or even a one-liner

[sorted(small_list, key=lambda x: -sum([y[0] for l in big_list for y in l  if y[1] == x[1]])) for small_list in big_list]

@Pankrat was close:

for inner in big_list:
    inner.sort()

You have a list of lists inside, so a simple list.sort() won't work on just that. You have to get into the inner level list to sort it (which holds the tuples).

Luckily, your case only requires you to sort the first element in the tuples; if you had to sort the others, then you would require something else, like so:

for inner in big_list:
    inner.sort(key = lambda x: x[i]) # i is the index location you want to sort on

My proposed solution:

[sublist.sort() for sublist in biglist]

afterwards the biglist is sorted. you don't have to assign the list-comprehension!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM