Python 標準庫之 collections 使用教程
點擊上方「
Python開發
」,選擇「置頂公眾號」
關鍵時刻,第一時間送達!
引言
Python為我們提供了4種基本的數據結構:list, tuple, dict, set,但是在處理數據量較大的情形的時候,這4種數據結構就明顯過於單一了,比如list作為單向鏈表在某些情形插入的效率會比較低,有時候我們也需要維護一個有序的dict。所以這個時候我們就要用到Python標準庫為我們提供的collections包了,它提供了多個有用的集合類,熟練掌握這些集合類,不僅可以讓我們讓寫出的代碼更加Pythonic,也可以提高我們程序的運行效率。
defaultdict的使用
defaultdict(default_factory)在普通的dict(字典)之上添加了default_factory,使得key(鍵)不存在時會自動生成相應類型的value(值),default_factory參數可以指定成list, set, int等各種合法類型。
example1
>>>
from
collections
import
defaultdict
>>>
s
=
[(
"red"
,
1
),
(
"blue"
,
2
),
(
"red"
,
3
),
(
"blue"
,
4
),
(
"red"
,
1
),
(
"blue"
,
4
)]
我們現在有上面這樣一組list(列表),雖然我們有6組數據,但是仔細觀察後發現其實我們只有兩種color(顏色),但是每一個color對應多個值。現在我們想要將這個list轉換成一個dict(字典),這個dict的key(鍵)對應一種color,dict的value(值)設置為一個list存放color對應的多個值。我們可以使用defaultdict(list)來解決這個問題。
# d可以看作一個dict(字典),dict的value是一個list(列表)
>>>
d
=
defaultdict
(
list
)
>>>
for
k
,
v
in
s
:
...
d
[
k
].
append
(
v
)
...
>>>
d
defaultdict
(
<
class
"list"
>
,
{
"blue"
:
[
2
,
4
,
4
],
"red"
:
[
1
,
3
,
1
]})
example2
上面這個例子中有一些不完美的地方,比如說{『blue』: [2, 4, 4], 『red』: [1, 3, 1]}這個defaultdict中blue顏色中包含兩個4,red顏色中包含兩個1,但是我們不希望含有重複的元素,這個時候可以考慮使用defaultdict(set)來解決這個問題。set(集合)相比list(列表)的不同之處在於set中不允許存在相同的元素。
>>>
d
=
defaultdict
(
set
)
>>>
for
k
,
v
in
s
:
...
d
[
k
].
add
(
v
)
...
>>>
d
defaultdict
(
<
class
"set"
>
,
{
"blue"
:
{
2
,
4
},
"red"
:
{
1
,
3
}})
example3
>>> s = "hello world"
通過使用defaultdict(int)的形式我們來統計一個字元串中每個字元出現的個數。
>>>
d
=
defaultdict
(
int
)
>>>
for
k
in
s
:
...
d
[
k
]
+=
1
...
>>>
d
defaultdict
(
<
class
"int"
>
,
{
"o"
:
2
,
"h"
:
1
,
"w"
:
1
,
"l"
:
3
,
" "
:
1
,
"d"
:
1
,
"e"
:
1
,
"r"
:
1
})
OrderedDict的使用
我們知道默認的dict(字典)是無序的,但是在某些情形我們需要保持dict的有序性,這個時候可以使用OrderedDict,它是dict的一個subclass(子類),但是在dict的基礎上保持了dict的有序型,下面我們來看一下使用方法。
example1
>>>
from
collections
import
OrderedDict
# 無序的dict
>>>
d
=
{
"banana"
:
3
,
"apple"
:
4
,
"pear"
:
1
,
"orange"
:
2
}
這是一個無序的dict(字典),現在我們可以使用OrderedDict來讓這個dict變得有序。
# 將d按照key來排序
>>>
OrderedDict
(
sorted
(
d
.
items
(),
key
=
lambda
t
:
t
[
0
]))
OrderedDict
([(
"apple"
,
4
),
(
"banana"
,
3
),
(
"orange"
,
2
),
(
"pear"
,
1
)])
# 將d按照value來排序
>>>
OrderedDict
(
sorted
(
d
.
items
(),
key
=
lambda
t
:
t
[
1
]))
OrderedDict
([(
"pear"
,
1
),
(
"orange"
,
2
),
(
"banana"
,
3
),
(
"apple"
,
4
)])
# 將d按照key的長度來排序
>>>
OrderedDict
(
sorted
(
d
.
items
(),
key
=
lambda
t
:
len
(
t
[
0
])))
OrderedDict
([(
"pear"
,
1
),
(
"apple"
,
4
),
(
"orange"
,
2
),
(
"banana"
,
3
)])
example2
使用popitem(last=True)方法可以讓我們按照LIFO(先進後出)的順序刪除dict中的key-value,即刪除最後一個插入的鍵值對,如果last=False就按照FIFO(先進先出)刪除dict中key-value。
>>>
d
=
{
"banana"
:
3
,
"apple"
:
4
,
"pear"
:
1
,
"orange"
:
2
}
# 將d按照key來排序
>>>
d
=
OrderedDict
(
sorted
(
d
.
items
(),
key
=
lambda
t
:
t
[
0
]))
>>>
d
OrderedDict
([(
"apple"
,
4
),
(
"banana"
,
3
),
(
"orange"
,
2
),
(
"pear"
,
1
)])
# 使用popitem()方法來移除最後一個key-value對
>>>
d
.
popitem
()
(
"pear"
,
1
)
# 使用popitem(last=False)來移除第一個key-value對
>>>
d
.
popitem
(
last
=
False
)
(
"apple"
,
4
)
example3
使用move_to_end(key, last=True)來改變有序的OrderedDict對象的key-value順序,通過這個方法我們可以將排序好的OrderedDict對象中的任意一個key-value插入到字典的開頭或者結尾。
>>>
d
=
OrderedDict
.
fromkeys
(
"abcde"
)
>>>
d
OrderedDict
([(
"a"
,
None
),
(
"b"
,
None
),
(
"c"
,
None
),
(
"d"
,
None
),
(
"e"
,
None
)])
# 將key為b的key-value對移動到dict的最後
>>>
d
.
move_to_end
(
"b"
)
>>>
d
OrderedDict
([(
"a"
,
None
),
(
"c"
,
None
),
(
"d"
,
None
),
(
"e"
,
None
),
(
"b"
,
None
)])
>>>
""
.
join
(
d
.
keys
())
"acdeb"
# 將key為b的key-value對移動到dict的最前面
>>>
d
.
move_to_end
(
"b"
,
last
=
False
)
>>>
""
.
join
(
d
.
keys
())
"bacde"
deque的使用
list存儲數據的優勢在於按找索引查找元素會很快,但是插入和刪除元素就很慢了,因為它是是單鏈表的數據結構。deque是為了高效實現插入和刪除操作的雙向列表,適合用於隊列和棧,而且線程安全。
list只提供了append和pop方法來從list的尾部插入/刪除元素,但是deque新增了appendleft/popleft允許我們高效的在元素的開頭來插入/刪除元素。而且使用deque在隊列兩端添加(append)或彈出(pop)元素的演算法複雜度大約是O(1),但是對於list對象改變列表長度和數據位置的操作例如 pop(0)和insert(0, v)操作的複雜度高達O(n)。由於對deque的操作和list基本一致,這裡就不重複了。
ChainMap的使用
ChainMap用來將多個dict(字典)組成一個list(只是比喻),可以理解成合併多個字典,但和update不同,而且效率更高。
>>>
from
collections
import
ChainMap
>>>
a
=
{
"a"
:
"A"
,
"c"
:
"C"
}
>>>
b
=
{
"b"
:
"B"
,
"c"
:
"D"
}
>>>
m
=
ChainMap
(
a
,
b
)
# 構造一個ChainMap對象
>>>
m
ChainMap
({
"a"
:
"A"
,
"c"
:
"C"
},
{
"b"
:
"B"
,
"c"
:
"D"
})
>>>
m
[
"a"
]
"A"
>>>
m
[
"b"
]
"B"
# 將m變成一個list
>>>
m
.
maps
[{
"a"
:
"A"
,
"c"
:
"C"
},
{
"b"
:
"B"
,
"c"
:
"D"
}]
# 更新a中的值也會對ChainMap對象造成影響
>>>
a
[
"c"
]
=
"E"
>>>
m
[
"c"
]
"E"
# 從m複製一個ChainMap對象,更新這個複製的對象並不會對m造成影響
>>>
m2
=
m
.
new_child
()
>>>
m2
[
"c"
]
=
"f"
>>>
m
[
"c"
]
"E"
>>>
a
[
"c"
]
"E"
>>>
m2
.
parents
ChainMap
({
"a"
:
"A"
,
"c"
:
"C"
},
{
"b"
:
"B"
,
"c"
:
"D"
})
Counter的使用
example1
Counter也是dict的一個subclass,它是一個無序容器,可以看做一個計數器,用來統計相關元素出現的個數。
>>>
from
collections
import
Counter
>>>
cnt
=
Counter
()
# 統計列表中元素出現的個數
>>>
for
word
in
[
"red"
,
"blue"
,
"red"
,
"green"
,
"blue"
,
"blue"
]
:
...
cnt
[
word
]
+=
1
...
>>>
cnt
Counter
({
"blue"
:
3
,
"red"
:
2
,
"green"
:
1
})
# 統計字元串中元素出現的個數
>>>
cnt
=
Counter
()
>>>
for
ch
in
"hello"
:
...
cnt
[
ch
]
=
cnt
[
ch
]
+
1
...
>>>
cnt
Counter
({
"l"
:
2
,
"o"
:
1
,
"h"
:
1
,
"e"
:
1
})
example2
使用elements()方法按照元素的出現次數返回一個iterator(迭代器),元素以任意的順序返回,如果元素的計數小於1,將忽略它。
>>>
c
=
Counter
(
a
=
4
,
b
=
2
,
c
=
0
,
d
=-
2
)
>>>
c
Counter
({
"a"
:
4
,
"b"
:
2
,
"c"
:
0
,
"d"
: -
2
})
>>>
c
.
elements
()
<
itertools
.
chain object
at
0x7fb0a069ccf8
>
>>>
next
(
c
)
"a"
# 排序
>>>
sorted
(
c
.
elements
())
[
"a"
,
"a"
,
"a"
,
"a"
,
"b"
,
"b"
]
使用most_common(n)返回一個list, list中包含Counter對象中出現最多前n個元素。
>>>
c
=
Counter
(
"abracadabra"
)
>>>
c
Counter
({
"a"
:
5
,
"b"
:
2
,
"r"
:
2
,
"d"
:
1
,
"c"
:
1
})
>>>
c
.
most_common
(
3
)
[(
"a"
,
5
),
(
"b"
,
2
),
(
"r"
,
2
)]
namedtuple的使用
使用namedtuple(typename, field_names)命名tuple中的元素來使程序更具可讀性。
>>>
from
collections
import
namedtuple
>>>
Point
=
namedtuple
(
"PointExtension"
,
[
"x"
,
"y"
])
>>>
p
=
Point
(
1
,
2
)
>>>
p
.
__class__
.
__name_
_
"PointExtension"
>>>
p
.
x
1
>>>
p
.
y
2
來源:ZiWenXie
www.ziwenxie.site/2016/12/10/python-stand-library-collections/
Python開發整理髮布,轉載請聯繫作者獲得授權
【點擊成為Java大神】
TAG:Python開發 |