问题
I have a class named record, which stores information of log record;
class Record():
def __init__(self, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
And examples of this record can be:
r1 = Record(uid='001',url='www.google.com',status=200)
r2 = Record(uid='002',url='www.google.com',status=404)
r3 = Record(uid='339',url='www.ciq.com', status=200)
...
What I want is to count how many users each url has. So for "google", there are '001' and '002'. I usually use a Counter to record elements within a list and their appearances. But here, Counter seems just put the elements instead of counting them. Is there a lambda I can put or try?
I can go through all the staff though...
I think i may cause confusion here.
My key point is to group the objects by its attributes...So not only the url counting but also,
res = Counter(r)
(don't know how to put lambda inside or even that's possible) I can get maybe
res[0].url = 'www.google.com'
and its count is 2..?
And suggestion?
Thanks!
回答1:
There was a subtle bug in my previous answer, and while fixing it I came up with a much simpler and faster way to do things which no longer uses itertools.groupby()
.
The updated code below now features a function designed to do exactly what you want.
from collections import Counter
from operator import attrgetter
class Record(object):
def __init__(self, **kwargs):
for key, value in kwargs.iteritems():
setattr(self, key, value)
records = [Record(uid='001', url='www.google.com', status=200),
Record(uid='002', url='www.google.com', status=404),
Record(uid='339', url='www.ciq.com', status=200)]
def count_attr(attr, records):
""" Returns Counter keyed by unique values of attr in records sequence. """
get_attr_from = attrgetter(attr)
return Counter(get_attr_from(r) for r in records)
for attr in ('status', 'url'):
print('{!r:>8}: {}'.format(attr, count_attr(attr, records)))
Output:
'status': Counter({200: 2, 404: 1})
'url': Counter({'www.google.com': 2, 'www.ciq.com': 1})
回答2:
You should be able to just iterate over all the records and pass url values to Counter, like so:
records = [r1, r2, r3, ...]
url_counter = Counter(r.url for r in records)
print(url_counter['www.google.com'])
来源:https://stackoverflow.com/questions/28306700/python-how-to-use-counter-on-objects-according-to-attributes