如何基于每个子列表中的公共键创建新的子列表层以对子列表进行分类?

Posted

技术标签:

【中文标题】如何基于每个子列表中的公共键创建新的子列表层以对子列表进行分类?【英文标题】:How to create a new layer of sublists based on a common key within each sublist in order to categorize the sublists? 【发布时间】:2014-02-03 00:13:17 【问题描述】:

如何根据每个子列表中的公共键创建一个新的子列表层,以便对子列表进行分类?换句话说,如何将子列表放入列表中索引为 1 的每个项目都相同的新子列表中?

例如,我想将以下子列表列表转换为子列表列表,其中每个子列表位于一个新子列表中,其中索引 1 处的每个项目在该子列表中都是相同的。我想将此列表中的苹果、香蕉和橙子的子列表放入一个新的子列表中。

lsta = [['2014W01','apple',21,'apple@gmail.com'],['2014W02','apple',19,'apple@g.com'],['2014W02','banana',51,'b@gmail.com'],['2014W03','apple',100,'apple@gmail.com'],['2014W01','banana',71,'b@yahoo.com'],['2014W02','organge',21,'organge@gmail.com']]

我希望将苹果的三个子列表包含在一个新的子列表中,以及将香蕉的两个子列表包含在一个新的子列表中,等等。

Desired_List = [[['2014W01','apple',21,'apple@gmail.com'],['2014W02','apple',19,'apple@g.com'],['2014W03','apple',100,'apple@gmail.com']],[['2014W02','banana',51,'b@gmail.com'],['2014W01','banana',71,'b@yahoo.com']],[['2014W02','organge',21,'organge@gmail.com']]]

加分,如果您能告诉我如何进行多种分类(例如,不仅按水果类型分类,还按周分类)?

【问题讨论】:

您是否考虑过使用 dicts 代替? 好建议!我想我应该把问题改成在这种情况下我将如何使用字典 相关:***.com/questions/409370/… 【参考方案1】:
In [43]: import itertools as IT

In [44]: import operator

In [46]: [list(grp) for key, grp in IT.groupby(sorted(lsta, key=operator.itemgetter(1)), key=operator.itemgetter(1))]
Out[46]: 
[[['2014W01', 'apple', 21, 'apple@gmail.com'],
  ['2014W02', 'apple', 19, 'apple@g.com'],
  ['2014W03', 'apple', 100, 'apple@gmail.com']],
 [['2014W02', 'banana', 51, 'b@gmail.com'],
  ['2014W01', 'banana', 71, 'b@yahoo.com']],
 [['2014W02', 'organge', 21, 'organge@gmail.com']]]

【讨论】:

【参考方案2】:

通常情况下,我会在此使用 itertools.groupby,但只是为了好玩,这是一种手动完成所有繁重工作的方法

def transform(lista):
    d = 
    for subl in lista:
        k = subl.pop(1)
        if k not in d:
            d[k] = []
        d[k].append(subl)
    answer = []
    for k, lists in d.items():
        temp = []
        for l in lists:
            l.insert(1, k)
            temp.append(l)
        answer.append(temp)
    return answer

输出:

In [56]: transform(lsta)
Out[56]: 
[[['2014W02', 'organge', 21, 'organge@gmail.com']],
 [['2014W01', 'apple', 21, 'apple@gmail.com'],
  ['2014W02', 'apple', 19, 'apple@g.com'],
  ['2014W03', 'apple', 100, 'apple@gmail.com']],
 [['2014W02', 'banana', 51, 'b@gmail.com'],
  ['2014W01', 'banana', 71, 'b@yahoo.com']]]

【讨论】:

【参考方案3】:

我会采取一些不同的策略。您可能希望您的分组依据字段成为dict 中的查找值。该值可以只是一个list 的各种......无论你想在这里调用每个子列表。我会给每个人打电话FruitPerson

from collections import defaultdict, namedtuple

FruitPerson = namedtuple('FruitPerson','id age email')

d = defaultdict(list)

for sublist in lsta:
    d[sublist[1]].append(FruitPerson(sublist[0],*sublist[2:]))

那么,例如:

d['apple']
Out[19]: 
[FruitPerson(id='2014W01', age=21, email='apple@gmail.com'),
 FruitPerson(id='2014W02', age=19, email='apple@g.com'),
 FruitPerson(id='2014W03', age=100, email='apple@gmail.com')]

d['apple'][0]
Out[20]: FruitPerson(id='2014W01', age=21, email='apple@gmail.com')

d['apple'][0].id
Out[21]: '2014W01'

编辑:好的,多分类加分问题。你只需要嵌套你的字典。语法有点傻,因为defaultdict 的参数必须是可调用的;您可以使用lambdafunctools.partial 来做到这一点:

FruitPerson = namedtuple('FruitPerson','age email') #just removed 'id' field
d = defaultdict(lambda: defaultdict(list))

for sublist in lsta:
    d[sublist[1]][sublist[0]].append(FruitPerson(*sublist[2:]))

d['apple']
Out[37]: defaultdict(<type 'list'>, '2014W03': [FruitPerson(age=100, email='apple@gmail.com')], '2014W02': [FruitPerson(age=19, email='apple@g.com')], '2014W01': [FruitPerson(age=21, email='apple@gmail.com')])

d['apple']['2014W01']
Out[38]: [FruitPerson(age=21, email='apple@gmail.com')]

d['apple']['2014W01'][0].email
Out[40]: 'apple@gmail.com'

虽然老实说,此时您应该考虑升级到真正的关系数据库,该数据库可以理解 SELECT whatever FROM whatever WHERE something 类型的查询。

【讨论】:

以上是关于如何基于每个子列表中的公共键创建新的子列表层以对子列表进行分类?的主要内容,如果未能解决你的问题,请参考以下文章

关于python中的列表问题。把子列表当做母列表的元素,对子列表进行操作时,之前已添加的子列表的值会被改

如何制作每个 CSV 行的子列表并将该子列表放入列表中

如何提取每个子列表中每个元组的第一个元素?

appendChild(newnode)在指定节点的最后一个子节点列表之后添加一个新的子节点

如何将每个子列表加入 Python 中的单个字符串?

如何将嵌套字典列表与它们的值中的公共键相加? [复制]