如何根据索引值在python中过滤列表?

How to filter list in python based on index value?

提问人:Summer 提问时间:11/2/2023 最后编辑:Summer 更新时间:11/4/2023 访问量:130

问:

假设我有 2 个列表,记录了每个人每天吃的苹果数量:

people = ['乔治', '乔治', '乔治', '达纳', '约翰', '约翰']

apples_eaten = [5, 1, 3, 4, 3, 3]

在此方案中,我们有来自 George 的 3 天数据、来自 Dana 的 1 天数据和来自 John 的 2 天数据。

我想知道是否有代码可以根据“人员”列表过滤数据,以便我可以将 George 的数据与输出 [5, 1, 3] 一起拉取。

我想知道如果我以矩阵格式获得这些数据,每个数据集都是一行,以便索引排列,是否有办法更容易做到这一点?我正在从 csv 文件中提取这些列表,但我想知道我是否应该从 csv 文件中提取整个数据集作为矩阵。

专门寻找没有循环的代码,因为我可以很容易地用循环来编码它,但我只是想避免它,因为我的数据集很大,而且我的代码中已经有几个循环,所以我正在努力使它尽可能高效。

编辑: 我想最小化循环的原因是因为我有 4000 个“人”需要排序,比如说数字 1-4000,我需要将这些人映射到大约 11,000 个数据点。

我想到的循环是这样的:

unique_list = [] # list of people with unique IDs numbered 1-4000 
people = [] # list of 11,000 repeated ID numbers matching up with data points
data = [] # list of 11,000 data points 

 for i in len(unique_list) 
   data_sorted = []
   ID = unique_list[i]
   for x in len(data) 
       if people[x] = ID 
           data_sorted.append(data[x]) 
       else

所以我想避免这种情况的原因是,以我拥有的数据量,这将需要很长时间,而且我不认为这是最有效的代码。让我知道你们的想法,谢谢!

列表 CSV的 字典 索引

评论

1赞 deceze 11/2/2023
如果没有循环,您将无法真正做任何事情。为什么要限制循环?

答:

1赞 ShadowRanger 11/2/2023 #1

“没有循环”在这里是一个荒谬的条件。当数据没有可利用的结构时,循环是不可避免的。唯一理智的方法是使用循环;循环的少数替代方案将不得不通过额外的步骤完成所有相同的工作,可能以效率较低的方式完成。如果您没有看到循环,那是因为该循环隐藏在为您循环的 API 后面。

撇开这一点不谈,单个查找的解决方案是 listcomp over:zip

people = ['George', 'George', 'George', 'Dana', 'John', 'John']

apples_eaten = [5, 1, 3, 4, 3, 3]

person_data = [cnt for person, cnt in zip(people, apples_eaten) if person == 'George']

就是这样。有一个循环。它是 listcomp 的一部分,由 CPython 进行了大量优化。 本身也针对这种情况进行了大量优化(当它产生的每次都拆包时,它会重用相同的内容,因此不会发生分配)。在任何大小的数据中一次查找单个人都可以,但是您将为查找的每个人执行工作,因此,如果您需要查找多个人或数据中的所有人,则无法很好地扩展。ziptupletupleO(n)

如果您可能需要查找多个人,并且数据很少更改,则可以预先执行一些工作,以使每个单独的查找成本更低。最简单的解决方案是将每个人映射到他们的相关数据,例如:dictlist

from collections import defaultdict  # At top of file

person_to_eaten_count = defaultdict(list)

for person, cnt in zip(people, apples_eaten):
    person_to_eaten_count[person].append(cnt)

# Optionally convert back to plain `dict` to prevent future autovivification of keys
person_to_eaten_count = dict(person_to_eaten_count)

一旦你做到了这一点(成本并不比搜索一个人的数据高多少;它是为了构建 ,只是常数因子略高),为任何人查找数据就变得非常便宜; 将获取工作数据,您也可以为任何其他人做同样的事情。dictO(n)dictperson_to_eaten_count['George']GeorgeO(1)

-2赞 user_stack_overflow 11/2/2023 #2

它是这样的:

people = ['George', 'George', 'George', 'Dana', 'John', 'John']
apples_eaten = [5, 1, 3, 4, 3, 3]
dict1={}
i=0
for p in people:
    if p in dict1.keys():
        dict1[p].append(int(apples_eaten[i]))
    else:
        dict1[p]=list([])
        dict1[p].append(int(apples_eaten[i]))
    i+=1 
print(dict1)

输出:

{'George': [5, 1, 3], 'Dana': [4], 'John': [3, 3]}
-1赞 Alain T. 11/2/2023 #3

如果人名始终是连续且唯一的,则可以使用 groupby 函数从源列表中构建字典:

people = ['George', 'George', 'George', 'Dana', 'John', 'John']
apples_eaten = [5, 1, 3, 4, 3, 3]

from itertools import groupby
iPeople     = iter(people)
data_sorted = {p:g for p,(*g,) in
               groupby(apples_eaten,key=lambda _:next(iPeople))}

print(data_sorted)

{'George': [5, 1, 3], 'Dana': [4], 'John': [3, 3]}

如果名称不一定是连续的,则可以使用字典更新按名称组织结果:

data_sorted = dict()
data_sorted.update( (p,data_sorted.get(p,[])+[a]) 
                    for p,a in zip(people,apples_eaten) )

print(data_sorted)

[('George', [5, 1, 3]), ('Dana', [4]), ('John', [3, 3])]