提到遍历,最常出现的操作可能是for i in range(len())了,比如,对某个list遍历并保留符合条件数值的索引:
# 分组
# 前缀为st→ group1;前缀为ha→ group2
lst = ['stack','stand','happy','handle','store']
d_ = defaultdict(list)
for i in range(len(lst)):
if lst[i].startswith('sta'):
d_[1].append(i)
elif lst[i].startswith('ha'):
d_[2].append(i)
else:
continue
通过上面的例子可以看到这种遍历方式在数值调用和表示上都是比较麻烦的。
那么有没有更方便清爽的遍历方式呢?针对这个问题,下面本文将介绍针对不同对象的多种不同遍历方式,相信总有一种能适合你的需求~
通过本文你将了解到
万能的enumerate
enumerate不适用的情景
np.array多维数组遍历
字典遍历
pd.DataFrame遍历
enumerate作为python中的一种内置方法,支持对所有可迭代对象进行遍历,使用enumerate对对象进行遍历,返回一个迭代器,提供内部索引及其对应的数值。
>>>print([i for i in enumerate(lst)])
[(0, 'stack'), (1, 'stand'), (2, 'happy'), (3, 'handle'), (4, 'store')]
通过上例可以看到,enumerate将返回包含对象各索引和对应数值形成的元组的迭代器。
enumerate可以对所有可迭代对象进行遍历,这意味着python内置基本数据类型list,tuple,set,字符串等等,以及numpy数组等都可以作为对象,如下例:
集合遍历
# 集合遍历
>>>st = {1,2,-2,3,0,-1,'a','c'}
>>>for i,v in enumerate(st):
print(i,v)
0 0
1 1
2 2
3 3
4 a
5 -1
6 c
7 -2
元组遍历
# 元组遍历
>>>tpl = ('a','b','c','d')
>>>for i,v in enumerate(tpl):
print(i,v)
0 a
1 b
2 c
3 d
字符串遍历
# 字符串遍历
>>>s = '123'
>>>for i,v in enumerate(s):
print(i,v)
0 1
1 2
2 3
字典遍历
>>>d_ = {'a':1,'b':2}
>>>for i,v in enumerate(d_):
>>> print(i,v)
0 a
1 b
当enumerate的对象为字典时,与其他对象不同,返回的结果为key键值和其相应的索引。但是一般情况下,我们在谈到字典遍历时,更希望的操作是key键值和其所对应数值的组合,对于这个问题的解决将在后面内容实现。
array数组遍历
>>>ar = np.array(['a','b','c'])
>>>for i,v in enumerate(ar):
>>> print(i,v)
0 a
1 b
2 c
上述例子是一个一维数组,那么多维矩阵时呢?
>>>ar = np.array([[1,2,3],[4,5,6]])
>>>for i,v in enumerate(ar):
>>> print(i,v)
0 [1 2 3]
1 [4 5 6]
多维数组矩阵遍历时,enumerate遍历的结果为每行数值及其索引,并不是对每个元素进行遍历。那么如何实现遍历每个元素呢?此时第一反应可能是用一个多层循环来解决。但是不要忘了我们的目标-清清爽爽实现遍历!之后我们将介绍一种方法,对于多维数组实现遍历每个元素,返回包括索引和单个元素的迭代器。
pd.Series遍历
>>>sr = pd.Series(['a','b','c'],index=[5,6,7],name='name')
>>>for i,v in enumerate(sr):
>>> print(i,v)
0 a
1 b
2 c
pd.Series作为pandas基本数据结构之一,是一个可迭代对象,所以enumerate同样可以用来进行遍历。但需要注意的是,返回的索引是从0开始的隐含位置索引,并不受series本身索引的影响。
pd.DataFrame遍历
聪明的同学可能要问了,既然Series可以使用enumerate遍历,那么DataFrame是否可以呢?请看下面示例:
>>>df = pd.DataFrame({'a':[1,2,3],'b':[1,2,3]})
>>>df
a b
0 1 1
1 2 2
2 3 3
>>>for i,v in enumerate(df):
>>> print(i,v)
0 a
1 b
DataFrame作为对象时,遍历结果是对columns的遍历结果,返回columns的索引及其对应的数值。关于DataFrame的遍历,如何实现行遍历/列遍历等,将在下面的内容中进行介绍。
小结
通过上面的介绍,相信大家已经深刻领略到了enumerate大法的好处,对于列表,集合,元组,字符串,一维数组,Series等都可以使用enumerate进行遍历。但同时也留下了一些问题:
1. 字典如何实现键值对遍历
2. 多维数组如何实现单个元素遍历
3. DataFrame如何实现行/列遍历
读完下面的内容,相信以上问题都会有一个答案。
① np.nditer
在numpy中,np.nditer可以用来实现对数组的迭代遍历,实现对数组的迭代遍历。
>>>ar = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>>for i in np.nditer(ar):
>>> print(i)
1
2
3
4
5
6
7
8
9
使用np.nditer迭代遍历,可以返回对数组中每个元素按照行列顺序的遍历结果。同时,也可实现间隔n行/n列遍历:↓
# 间隔一行遍历
>>>for i in np.nditer(ar[::2]):
>>> print(i)
1
2
3
7
8
9
# 间隔一列遍历
>>>for i in np.nditer(ar[:,::2]):
>>> print(i)
1
3
4
6
7
9
但是这种方法的遍历结果仅包含数值自身,不返回相应索引。如果想要实现返回索引和数值的遍历,那么就要用到np.ndenumerate。
② np.enumerate
np.ndenumerate是np独有的遍历方法,与enumerate效果类似,可返回包含索引-数值对的迭代器。
>>>for i, v in np.ndenumerate(ar):
>>> print(i, v)
(0, 0) 1
(0, 1) 2
(0, 2) 3
(1, 0) 4
(1, 1) 5
(1, 2) 6
(2, 0) 7
(2, 1) 8
(2, 2) 9
对于字典我们通常使用字典内置方法将其转换为可遍历的元组数组后再进行遍历。
>>>d_ = {'a':1,'b':2}
>>>d_.items()
dict_items([('a', 1), ('b', 2)])
>>>for k,v in d_.items():
>>> print(k,v)
a 1
b 2
同样的,DataFrame中也提供了一些进行遍历的内置方法,包括:pd.iterrows,pd.iteritems,pd.itertuples。
① pd.DataFrame.iterrows - 行遍历
返回(index, Series)。其中与enumerate不同,索引为数据中的真实数值索引,而非位置索引。
>>>for i,r in df.iterrows():
>>> print('索引:',i)
>>> print(r)
索引: A
a 1
b 1
Name: A, dtype: int64
索引: B
a 2
b 2
Name: B, dtype: int64
索引: C
a 3
b 3
Name: C, dtype: int64
② pd.DataFrame.iteritems - 列遍历
返回(columns, Series)。
>>>for c,sr in df.iteritems():
>>> print("索引:",c)
>>> print(sr)
索引: a
0 1
1 2
2 3
Name: a, dtype: int64
索引: b
0 1
1 2
2 3
Name: b, dtype: int64
③ pd.DataFrame.itertuples - 行遍历(具名元组)
行遍历,返回(index, 具名元组)。上面的方法中,数值均为Series,而itertuples则返回具名元组,使用起来更为方便,速度也相对更快。
>>>for i in df.itertuples():
>>> print(i)
Pandas(Index='A', a=1, b=1)
Pandas(Index='B', a=2, b=2)
Pandas(Index='C', a=3, b=3)
具名元组调用元素,可使用名称/索引调用两种方式实现:
>>>i
Pandas(Index='C', a=3, b=3)
>>>i.a
3
>>>i[0]
'C'
遍历结果中的具名元组默认名称为Pandas,同时索引默认出现在元组中。可通过修改参数对以上设定进行修改。
# 修改具名元组默认名
>>>for i in df.itertuples(name='test'):
>>> print(i)
test(Index='A', a=1, b=1)
test(Index='B', a=2, b=2)
test(Index='C', a=3, b=3)
# 不显示索引
>>>for i in df.itertuples(index=False):
>>> print(i)
Pandas(a=1, b=1)
Pandas(a=2, b=2)
Pandas(a=3, b=3)
现在对于刚才提出的三个问题就已经解答完毕了。 关于遍历的内容就介绍到这儿,希望看到这里的小伙伴对于python中常用数据结构的遍历方法都有了较为系统了解。