Remrinのpython攻略日記

python3に入門しました。python3についてあれこれとサンプルコードとか。

pythonのリスト操作

pythonのlist型はよく使うのに覚えることがたくさん。
調べる手間を省きたいので備忘録です。
 

list型の概要

・シーケンス型の一つで、iterable
・numpyのndarrayなどの配列と違い、バラバラなメモリに紐つけで末尾追加が可能。
・要素(element)は数値に限らず、あらゆる型のオブジェクト。型の混在も可能
・list型のオブジェクトも要素になる。 [[1, 2], [3, 4], [5, 6]]
・index指定で要素を特定できる。
・多次元のlistの要素は list1[0][1]などで表し、左側の[0]が外側を表す。
・スライスが使用できる。
 スライスは範囲を超えてもエラーが出ない。
・文字列と違い、スライス代入ができる。 list1[1:2] = [6, 7, 8, 9]
listという変数名を使うとbuilt-inのlist関数を隠蔽してしまう。

list = [1, 3, 5]
list(range(5))   #エラー:'list' object is not callable

隠蔽してしまったらdel listとすることでローカルのlistが削除され、もとに戻る
 
○リストの要素数 len(list1)

list1 = [[1, 2, 3],
         [4, 5, 6]]
len(list1)          #2   外側の要素数(2次元配列の列の数)
len(list1[0])       #3   内側の要素数(2次元配列の行の数)

 

リストの生成

list1 = [1, 3, 5]                   #[1, 3, 5]
list2 = "Hello world".split()       #['Hello', 'world']
list3 = list("Hello")               #['H','e','l','l','o']
list4 = list(range(5))              #[0, 1, 2, 3, 4]
list5 = list(map(abs, range(-5, 0)))#[5, 4, 3, 2, 1]
#list0 = list(0)                     #エラー:数値はiterableではない
list6 = [0, 1, 2, 3, 4, 5, 6][1::2] #[1, 3, 5]
list7 = list6[::-1]                 #[5, 3, 1]
list8 = list7.copy()                #[5, 3, 1]
list9 = [i*5 for i in range(5)]     #[0, 5, 10, 15, 20]


注意:
list2 = list1 とすると、list2とlist1が同じオブジェクト(同じアドレス)を参照する。
そのため、一方の要素を変更するともう一方の要素まで変更されてしまう。

list1 = [1, 3, 5]
list2 = list1
print(list1, list2)     #[1, 3, 5] [1, 3, 5]
list2[0] = 10           #list2の0番要素を10にすると
print(list1, list2)     #[10, 3, 5] [10, 3, 5]

 
回避方法:
 ・list2 = list1.copy()
 ・list2 = list(list1)
 ・list2 = list1[:]
 ・map()やfilter()などを使う
 

追加、結合、挿入

list1 = [1, 3, 5]
list4 = list(range(5))
list1.append(10)        # [1, 3, 5, 10]
list1[len(list1):] = [7]# [1, 3, 5, 7]
list1.append([10, 11])  # [1, 3, 5, [10, 11]]
list1.extend([10, 11])  # [1, 3, 5, 10, 11]
list1.extend(list4)     # [1, 3, 5, 0, 1, 2, 3, 4]
list1 += list4          # [1, 3, 5, 0, 1, 2, 3, 4]
list1 *=3               # [1, 3, 5, 1, 3, 5, 1, 3, 5]
list1.insert(2, 10)     # [1, 3, 10, 5] 2番要素の前に10を挿入
list1[2:2] = [10, 11]   # [1, 3, 10, 11, 5] 2番要素の前に10と11を挿入

 

削除

del list1[1:2]          #スライスされた要素を削除
p = list1.pop()         #末項を値として返し、listからは削除
p = list1.pop(0)        #0番要素を値として返し、listからは削除
list1.remove(5)         #最初に見つかった5を削除。位置不明のとき。存在しないとエラー

del list1[:]            #全要素を削除し、空のリストになる
list1.clear()           #全要素を削除し、空のリストになる
list1 = []              #全要素を削除し、空のリストになる
del list1               #list1自体を削除。メモリを解放

 

検索

list1 = [1, 3, 5, 7, 1, 3, 5, 7]
3 in list1             #True    
3 not in list1         #False
list1.index(3)         #1  3という要素の初登場index
list1.count(3)         #2  3という要素の登場回数

 

ソート(並べ替え)

  ソートはlist.sort()メソッドとsorted(list)関数の2つがある。
  いずれも昇順(ascending order)
  オプションでreverse=Trueとすると、降順(descending order)でソート
・list.sorted()メソッド
  元のリスト自体を破壊的にソート。元のlistが不要なときに使う。
  list型のオブジェクトのみに使える。
  返り値はNone(高速化処理などで稀に使う)
・sorted(iterable)関数
  元のリストは残したまま、新たなリスト型オブジェクトを作る。
  対象となるのはiterableなオブジェクト(リスト型、タプル型、辞書型など)
  タプル型は[0]の要素を基準に並べ替える。
・keyオプション
  keyオプションは比較する前に、全要素に対する処理を行う関数を指定。
  タプル型の[1]の要素を基準にしたりできる。
  sortメソッドもsorted関数もkeyオプションを付けられる。
  

・要素の全入れ替え
 list1.reverse() #リストの要素の順番をすべて逆にする。ソートではない。
 list1 = list1[::-1] #リストの要素の順番をすべて逆にした新しいリストを得る。

#シンプルな並べ替え
list1 = [5, 3, 1, 7]
list1.sort()           #[1, 3, 5, 7]   返り値はNone
list1 = sorted(list1)  #[1, 3, 5, 7]   返り値は[1, 3, 5, 7]

list1.reverse()        #[7, 5, 3, 1]   返り値はNone
list1 = list1[::-1]    #[7, 5, 3, 1]   返り値は[7, 5, 3, 1]

 

#いろいろな並べ替え
list1 = ["I", "am", "a", "python"]     #小文字としてソート
list1.sort(key=str.lower)              #['a', 'am', 'I', 'python']

list1 = [(1, "c"), (2, "a"), (3, "t")] #各タプルの2番目の要素、つまり[1]で。
list1.sort(key=lambda x:x[1])          #[(2, 'a'), (1, 'c'), (3, 't')]

list1 = [3, 1, 5]
list1.sort(reverse=True)               #[5, 3, 1]

 
2番要素[1]でソートし、次に1番要素[0]でソートする場合

from operator import itemgetter
list1 = [(3, "b"), (5, "a"), (7, "b"), (1, "a")]
sorted(list1, key=itemgetter(1, 0))   
#[(1, 'a'), (5, 'a'), (3, 'b'), (7, 'b')]

 

リストから重複を取り除く

list(set(list1))                     #順番をきにしないとき
sorted(set(list1))                   #ソートしたリストのとき
sorted(set(list1), key=list1.index)  #初登場順を維持するとき

 

リストをスタックとして使う

 LIFO(last in first out)として使う方法

list1 = [1, 3, 5]
list1.append(7)    # 末尾に追加する
list1.append(9)

print(list1.pop()) # 末尾から取り出す
print(list1.pop())

 

リストをキューとして使う。

 FIFO(first in first out)として使う。
 pop(0)で最初の要素を取り出せるが、動作が遅いのでcollectionsのdequeを使うのがよい。
 dequeはリストの両端での追加、取り出しが高速に実行できる。

from collections import deque
q = deque([1, 3, 5])
q.append(7)
q.appendleft(-1)
print(q)           # deque([-1, 1, 3, 5, 7])

print(q.pop())     # 7
print(q.popleft()) # -1
print(q)           # deque([1, 3, 5])