Python:通过字段拆分对象列表的更好方法?

时间:2017-05-04 02:05:07

标签: python list

我有一个名为person的对象列表及其国家/地区:

class Person(object):
    def __init__(self, id, country):
        self.id = str(id)
        self.country = str(country)

列表如下所示,其中id仅为UUID,国家/地区为国家/地区代码,我按国家/地区对其进行了排序:

('7e569521-69fe-4ccf-a898-254bd758bff0', 'AF')
('c6b45478-6901-4a22-aab8-7167397d4b13', 'AF')
('15aee743-a1b1-4a77-b93b-17786c8c8fab', 'AF')
('7ef1efd3-6b77-4dfe-b133-035eff76d7f6', 'AF')
('95880e05-9984-48e3-a60a-0cf52c2915ae', 'AG')
('620862a0-e888-4b20-8057-085122226050', 'AL')
('ed0caf58-e132-48ad-bfca-8a4df2b0c351', 'AL')
('730cf6ba-0981-4a0b-878e-5df0ebedaa99', 'AM')
('93f87a3d-d618-4e9a-9f44-4a1d0bc65bdc', 'AM')

现在我想按国家/地区将它们分成不同的列表。

这就是我现在正在做的事情:

prev_country = ""
person_data_country = []

for person in persons_data:

    if prev_country != person.country:
        if len(person_data_country) > 0:
            # do something with this new list by country

            # clear them    
            person_data_country = []

    # append item to new list
    person_data_country.append(person)
    prev_country = person.country

# last list, if any
if len(person_data_country) > 0:
    # do something with this new list by country

我通过上述代码得到了我想要的东西。

但我想知道是否有更好或更有效的方法根据国家/地区拆分列表?

3 个答案:

答案 0 :(得分:4)

您可以使用itertools.groupbyhttps://docs.python.org/3.6/library/itertools.html#itertools.groupby)来实现您的目标:

from itertools import groupby
grouped_data = groupby(persons_data, key=lambda x: x[1])  # or x.country, depending on your input list
for country, items in grouped_data:
    # do whatever you want

要记住一些问题:

  1. groupby返回一个迭代器,因此您只能迭代一次。
  2. 上面示例中的items也是一个迭代器。因此,如果您希望稍后通过索引访问各个项目,则需要将其强制转换为列表。

答案 1 :(得分:2)

您可以使用itertools.groupby。鉴于persons_data已经按国家/地区排序,以下代码可以执行您想要的操作:

import itertools
import operator

bycountry = operator.attrgetter("country")

all_people_by_country = []

for country, groupiter in itertools.groupby(persons_data, bycountry):
    all_people_by_country.append(list(groupiter))

答案 2 :(得分:1)

考虑我是否正确理解你的另一种方法:

from collections import defaultdict
persons = [
    Person('one', 'AF'),
    Person('two', 'AF'),
    Person('three', 'AG')
]
persons_by_country = defaultdict(list)
for person in persons:
    persons_by_country[person.country].append(person.id)

或者,如果您出于某种原因想要避免defaultdict

persons_by_country = {}
for person in persons:
    if person.country in persons_by_country:
        persons_by_country[person.country].append(person.id)
    else:
        persons_by_country[person.country] = [person.id]

无论哪种方式,结果都是:

{'AG': ['three'], 'AF': ['one', 'two']}

这方面的主要缺点是所有数据都存储在内存中两次。