0

I have a list with dates and each dict in the list has another list:

list = [
  {
    'date': 'X',
    'tickets': [
      { 'price': 100 },
      { 'price': 120 },
      { 'price': 100 },
      { 'price': 100 },
    ]
  },
  {
    'date': 'Y',
    'tickets': [
      { 'price': 300 },
      { 'price': 300 },
      { 'price': 100 },
      { 'price': 100 },
    ]
  }
]

Right now I am looping through the dates with

print('Date, Number of Tickets')
print('============')

for element in list:
  print(element.date + ' - ' + len(element.tickets))

which prints

Date, Number of Tickets
============
X - 4
Y - 4

but what I want it to print is

Date, Number of Tickets, Price
============
X - 3 - 100
X - 1 - 120
Y - 2 - 300
Y - 2 - 100

So I need it to group the list of tickets and loop through each group.

So it might be something like

print('Date, Number of Tickets, Price')
print('============')

for element in list:
  groups = group_by(element.tickets, 'price')

  for group in groups:
    print(element.date + ' - ' + group.num_tickets + ' - ' + group.price)

but I don't know how to group the tickets by price. Also, if there are no tickets for the date (i.e., tickets = []), then I still need a row saying with date=?, num_tickets=0, and price=None.

3
  • 1
    dict in python3.x doesn't support .(dot) access to keys. Commented Aug 17, 2017 at 10:06
  • I dunno why you might want to group, but a quick way to get a list of prices is prices = [ticket['price'] for ticket in element['tickets']]. Commented Aug 17, 2017 at 10:07
  • 1
    Advice: do not use build-in names as variables (list). Commented Aug 17, 2017 at 10:15

3 Answers 3

1

Loop over your data and accumulate the ticket prices into a collections.Counter then print out the results, eg:

from collections import Counter

for item in data:
    if not item['tickets']:
        print(item['date'], 0, 'None', sep=' - ')
        continue
    for price, count in Counter(el['price'] for el in item['tickets']).items():
        print(item['date'], count, price, sep=' - ')

Gives you:

X - 1 - 120
X - 3 - 100
Y - 2 - 100
Y - 2 - 300
Sign up to request clarification or add additional context in comments.

3 Comments

This is a nice solution if OP isn't worried about ordering. However, if ordering is necessary, then a sorted call will be needed.
@cᴏʟᴅsᴘᴇᴇᴅ well yes... but whether the ordering is by entry order, number of tickets for a price or by price order - can be done appropriately in a couple of places... The advantage to this over a groupby is that we're not having to pre-sort the list to aggregate it... and even if we did need to sort it in key order, there's likely to be a smaller set of rows needing sorting after grouping than prior.
Acknowledged, I complemented this solution for that very reason :)
0

I believe you're looking for itertools.groupby. In order for this to work, you'll need to sort the price items first.

import itertools

list_ = ...

for element in list_:
    groups = [list(g) for _, g in itertools.groupby(sorted(element['tickets'], key=lambda x: x['price']))]

    if groups:
        for group in groups:
            print(element['date'], len(group), group[0]['price'], sep=' - ')
    else:
        print(element['date'], 0, None, sep=' - ')

Output:

X - 3 - 100
X - 1 - 120
Y - 2 - 100
Y - 2 - 300

Don't name a list as list, or a dict as dict, or any other builtin name.


Now, setting list_[1]['tickets'] = []...

X - 3 - 100
X - 1 - 120
Y - 0 - None

4 Comments

But won't I be able to experience that groups might be empty and then not print anything?
@Jamgreen Groups are always size 1 or more.
Slight snag with this... Do a list_[1]['tickets'] = [] and re-run... it doesn't quite meet the note in the Q: Also, if there are no tickets for the date (i.e., tickets = []), then I still need a row saying with date=?, num_tickets=0, and price=None
@JonClements Fixed it now. Thanks a bunch for not downvoting.
0

First: iterate all prices to create list, then sort it. Second: feed sorted list of prices to Counter. Then combine it in list of dictionaries with date.

from collections import Counter

data = <data with ticket prices here>

tickets = [{'date': x['date'], 'tickets_by_price': Counter(sorted([y['price'] for y in x['tickets']]))} for x in data]

Result:

[
    {
        'tickets_by_price': Counter({100: 3, 120: 1}), 
        'date': 'x'
    },
    {
        'tickets_by_price': Counter({300: 2, 100: 2}),
        'date': 'y'
    }
 ]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.