情報処理: 覚え書き
1. 主なデータの管理・取り出し方法
- LIFO (Last-In First-Out): キューなどに使われる。
- FIFO (First-In First-Out): スタック。再帰的な処理をする際、実行中の状態を保存しておく為にも使われる。
- LFU (Least Frequently Used): 参照頻度が最も少ないものを取り出す。
- LRU (Least Recently Used): 未使用時間が最も長いものを取り出す。
1. 主なデータの管理・取り出し方法
2つのリストの要素を比較する際、リスト型をset型に変えると「-」「&」などの演算子1つで集合演算できます(AND、OR、NOTとか)。
#!/usr/bin/python
# coding: UTF-8
# リストの比較(by 集合演算)
old_list = ['A', 'B', 'C', 'D', 'E', 'F'] # 古いリスト
new_list = ['A', 'C', 'F', 'G', 'H', 'I'] # 更新された新しいリスト、とする
# 組み込み関数set()を用いて(リストを含む)シーケンス型からset型データを作成
old_set = set(old_list)
new_set = set(new_list)
print 'old_set ==', old_set
print 'new_set ==', new_set
# 差集合: old_setの要素からnew_setに含まれる要素を削除した要素集合
# すなわち、old_setをnew_setに更新した際に、削除された要素集合、とみる
print 'old_set - new_set ==', old_set - new_set
print 'len(old_set - new_set) ==', len(old_set - new_set) # 削除された個数
# old_setをnew_setに更新した際に、追加された要素集合、とみる
print 'new_set - old_set ==', new_set - old_set
print 'len(new_set - old_set) ==', len(new_set - old_set) # 追加された個数
# old_setをnew_setの共通要素集合(更新した際に変更されなかった要素、とみる)
print 'new_set & old_set ==', new_set & old_set
# old_setかnew_setに含まれる要素集合
print 'new_set ^ old_set ==', new_set ^ old_set
# 和集合: old_setとnew_setに含まれる重複の無い要素集合
print 'new_set | old_set ==', new_set | old_set
old_set == set(['A', 'C', 'B', 'E', 'D', 'F'])
new_set == set(['A', 'C', 'G', 'F', 'I', 'H'])
old_set - new_set == set(['B', 'E', 'D'])
len(old_set - new_set) == 3
new_set - old_set == set(['I', 'H', 'G'])
len(new_set - old_set) == 3
new_set & old_set == set(['A', 'C', 'F'])
new_set ^ old_set == set(['B', 'E', 'D', 'G', 'I', 'H'])
new_set | old_set == set(['A', 'C', 'B', 'E', 'D', 'G', 'F', 'I', 'H'])
リスト(and シーケンス型)をset型に変更すると要素の順序が失われます。再度リスト型に戻したいときは、list()関数を用います。
>>> set_data = set(['a', 'b', 'c', 'd'])
>>> set_data
set(['a', 'c', 'b', 'd'])
>>> list_data = list(set_data)
>>> list_data
['a', 'c', 'b', 'd']
>>> type(list_data)
<type 'list'>
>>>
話変わりますが、Rubyだと配列のまま加減算ができます(配列オブジェクトが「+」「-」演算子などをサポートしているみたい)。
データの順序が存在するデータ型としてシーケンス型があり、リストの上位型となっています。このシーケンス型には要素の抽出や操作を簡略化する分かりやすい構文がありますので、これを確認してみましょう。
#!/usr/bin/python
# coding: UTF-8
a = [10, 20, 30, 40, 50]
print 'a ', a
print 'a[0:] ', a[0:]
print 'a[1:] ', a[1:]
print 'a[-1:] ', a[-1:]
print 'a[-5:] ', a[-5:]
a [10, 20, 30, 40, 50]
a[0:] [10, 20, 30, 40, 50]
a[1:] [20, 30, 40, 50]
a[-1:] [50]
a[-5:] [10, 20, 30, 40, 50]
a = [10, 20, 30, 40, 50]
print 'a ', a
print 'a[:3] ', a[:3] # a[0] a[1] a[2]まで
print 'a[:-1] ', a[:-1] # Yは-1よりa[(-1)-1]→a[-2]までのリスト
print 'a[:-5] ', a[:-5]
a [10, 20, 30, 40, 50]
a[:3] [10, 20, 30]
a[:-1] [10, 20, 30, 40]
a[:-5] []
a = [10, 20, 30, 40, 50]
print 'a ', a
print 'a[::1] ', a[::1] # 1間隔なのでaと同じ
print 'a[::2] ', a[::2]
print 'a[::-1]', a[::-1] # 「-」を付けると逆順に辿っていきます
a [10, 20, 30, 40, 50]
a[::1] [10, 20, 30, 40, 50]
a[::2] [10, 30, 50]
a[::-1] [50, 40, 30, 20, 10]
リストの要素順序を逆順にする処理を構文で賄えるのは良いですね。
a = [10, 20, 30, 40, 50]
print 'a ', a
print 'a[1:3] ', a[1:3]
print 'a[:-1:2] ', a[:-1:2]
print 'a[-1::-2]', a[-1::-2]
print 'a[1:4:2] ', a[1:4:2]
a [10, 20, 30, 40, 50]
a[1:3] [20, 30]
a[:-1:2] [10, 30]
a[-1::-2] [50, 30, 10]
a[1:4:2] [20, 40]
文字列を比較する際に、大文字・小文字を区別したくない場合があります。その時は、比較する文字列を大/小文字列のどちらかに統一しておく、という手があります。Pythonでは大文字・小文字変換メソッドlower()、upper()はstringオブジェクトに組み込まれています。 今回は、その使い方と実際に使用する状況に近いデータ構造、ここでは変換対象文字列がリスト中の要素である場合を想定し、for文とリストコンプリヘンション(リスト内包表記)の両表記を以下に示します。
#!/usr/bin/python
# coding: UTF-8
# リスト中の文字列要素を大文字⇔小文字変換
str_atog = "ABCDEFG"
str_hton = "hijklmn"
# lower(), upper()メソッドの使い方
print "大文字(列) %s を小文字(列) %s に変換" % (str_atog, str_atog.lower())
print "小文字(列) %s を大文字(列) %s に変換" % (str_hton, str_hton.upper())
print
arr = ['And', 'Begin', 'Code', 'Double']
arr2 = ['end', 'flag', 'gem', 'halt']
# for文で小文字[大文字](列)を要素とするリストを生成
n_arr = []
for str in arr:
n_arr.append(str.lower())
print n_arr
n_arr2 = []
for str in arr2:
n_arr2.append(str.upper())
print n_arr2, 'n'
# リストコンプリヘンションで小文字[大文字](列)を要素とするリストを生成
print [str.lower() for str in arr]
print [str.upper() for str in arr2]
大文字(列) ABCDEFG を小文字(列) abcdefg に変換
小文字(列) hijklmn を大文字(列) HIJKLMN に変換
['and', 'begin', 'code', 'double']
['END', 'FLAG', 'GEM', 'HALT']
['and', 'begin', 'code', 'double']
['END', 'FLAG', 'GEM', 'HALT']
List Comprehensions ならワンライナーで書けるってのは地味に良いですね。 話変わりますが、Rubyにもイテレータやブロックを用いた簡略記法がありましたね。アレはアレで、応用しやすいものです。
if/for文中で使われるin演算子の評価はオブジェクトごとに微妙に変化します。あやふやなままにしておくのもなんですし、ここで、以下のオブジェクトに対するif/for文中の評価を実際に確認してみましょう。
#!/usr/bin/python
# coding: UTF-8
str1 = "abcdefghijklmn" # 文字列
# if 「検索する文字列」 in 「検索される文字列」:
elem = 'def'
if elem in str1:
print '文字列 "%s" に "%s" は存在する。' % (str1, elem)
print
# for 「要素(文字)」 in 「文字列」:
for ch in str1:
print ch, # str1の先頭の文字から順に繰り返す
文字列 "abcdefghijklmn" に "def" は存在する。
a b c d e f g h i j k l m n
#!/usr/bin/python
# coding: UTF-8
nums = [1, 2, 3, 4, 5] # 数値のリスト
chs = ['a', 'b', 'c', 'd'] # 文字列のリスト
dics = [{'one':1}, {'two':2}, {'three':3}, {'four':4}] # 辞書のリスト
# if 「検索する要素」 in 「検索されるリスト」:
elem = 3
if elem in nums:
print 'リスト %s に要素の %d は存在する。' % (nums, elem)
elem = 'b'
if elem in chs:
print 'リスト2 %s に要素の %s は存在する。' % (chs, elem)
elem = {'two':2}
if elem in dics:
print 'リスト3 %s に要素の %s は存在する。' % (dics, elem)
print
# for 「リストの要素」 in 「リスト」:
for e_num in nums:
print e_num,
print
for e_ch in chs:
print e_ch,
print
for e_dic in dics:
print e_dic,
リスト [1, 2, 3, 4, 5] に要素の 3 は存在する。
リスト2 ['a', 'b', 'c', 'd'] に要素の b は存在する。
リスト3 [{'one': 1}, {'two': 2}, {'three': 3}, {'four': 4}] に要素の {'two': 2} は存在する。
1 2 3 4 5
a b c d
{'one': 1} {'two': 2} {'three': 3} {'four': 4}
#!/usr/bin/python
# coding: UTF-8
dic = {'one':1, 'two':2, 'three':3, 'four':4} # 辞書
# if 「検索するキー」 in 「検索される辞書」:
elem = 'three'
if elem in dic: # 辞書のキーの検索
print '辞書 %s に要素の「キー」 %s は存在する。' % (dics, elem)
print
# for 「辞書のキー」 in 「辞書」:
for key in dic: # for key in dic.keys(): と同じ
print key,
print
for v in dic.values(): # 値を要素として繰り返す
print v,
print
for (k, v) in dic.items(): # (キー, 値)のタプルを要素として繰り返す
print "%s:%s, " % (k, v),
辞書 [{'one': 1}, {'two': 2}, {'three': 3}, {'four': 4}] に要素の「キー」 three は存在する。
four three two one
4 3 2 1
four:4, three:3, two:2, one:1,
リスト内包表記を知ることでコードのリーディングとライティングを早めることが出来ます(パフォーマンスもfor文より良いです)。そこでリスト内包表記とfor文の書き換え方を以下に紹介。
#!/usr/bin/python
# coding: UTF-8
# リスト内包表記(リストコンプリヘンション)をfor文に書き換える
# List Comprehensions
print [a for a in range(10)]
# 0~9の数値を要素とするリスト
a2 = []
for i in range(10):
a2.append(i)
print a2
print [b*2 for b in range(10)] # ループのパラメータに演算を行う
# 0~9の数値の×2の結果を要素とするリスト
b2 = []
for i in range(10):
b2.append(i*2)
print b2
print [c for c in range(10) if c % 2 == 1] # 条件を指定してリストを生成
# in の被演算子を評価後、取り出された要素cをif文にかける。if文が偽のときは、とばして次のループに入る
# 結果として、0~9の数値の中で条件「c % 2 == 1」を満たす、すなわち奇数を要素とするリスト
c2 = []
for i in range(10):
if (i % 2 == 1):
c2.append(i)
print c2
print '\n', b2
print [d+1 for d in b2]
d2 = []
for i in b2:
d2.append(i+1)
print d2
e = 'It is important to set my aims but at the same time I should confirm my present condition.'
print '\n', e
print [wd for wd in e.split(' ')]
e2 = []
for i in e.split(' '):
e2.append(i)
print e2
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
[1, 3, 5, 7, 9]
[1, 3, 5, 7, 9]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
It is important to set my aims but at the same time I should confirm my present condition.
['It', 'is', 'important', 'to', 'set', 'my', 'aims', 'but', 'at', 'the', 'same', 'time', 'I', 'should', 'confirm', 'my', 'present', 'condition.']
['It', 'is', 'important', 'to', 'set', 'my', 'aims', 'but', 'at', 'the', 'same', 'time', 'I', 'should', 'confirm', 'my', 'present', 'condition.']
[新しいリストに格納する要素(*1) for OLD_ELEMENT in OLD_LIST if 条件式] *1: 式を書く
>>> str = 'hello! hello!'
>>> ' '.join([c.upper() for c in str])
'H E L L O ! H E L L O !'
>>>
ここでの処理内容は、upper()メソッドによる英小文字→大文字の変換です。
#!/usr/bin/python
# coding: UTF-8
# リストの要素の追加と削除(取出し) | append()、extend()、pop()、remove()メソッドの使い方
a = [3, 5, 7, 9, 11]
print a
a.append(13) # 引数のオブジェクトをリストの末尾に追加
print a
a.extend([15, 17, 19, 21]) # 引数のシーケンスを展開して末尾に追加
print a
elm = a.pop() # リストの末尾から要素を1つ取り出す
print 'elm == %d' % elm
print a
elm = a.pop(4) # 引数にリストのインデックスを取り、その要素を取り出す
print 'elm == %d' % elm
print a
a.remove(13) # 引数のオブジェクトをリスト要素から削除する
print a
[3, 5, 7, 9, 11]
[3, 5, 7, 9, 11, 13]
[3, 5, 7, 9, 11, 13, 15, 17, 19, 21]
elm == 21
[3, 5, 7, 9, 11, 13, 15, 17, 19]
elm == 11
[3, 5, 7, 9, 13, 15, 17, 19]
[3, 5, 7, 9, 15, 17, 19]
#!/usr/bin/python
# coding: UTF-8
# リストの初期化
num1 = [1, 4, 7, 12, 23, 41, 88, 96]
num2 = [100, 130, 255, 1000]
str1 = ['Jon', 'Mery', 'Sun', 'Ren']
str2 = ['hi', 'hello', 'hey', 'bye', 'ya']
# リストの要素を出力
print num1[3]
print num2[-2]
print
# リストの範囲を指定して抽出(シーケンス型に備わっている操作)
extr_n1 = num1[:-3] # 先頭から最末尾の3つ手前の要素までのリストを抽出
print extr_n1
extr_n2 = num1[2:] # 添え字の2から末尾までの要素のリストを抽出
print extr_n2
extr_s1 = str2[1:-2] # 添え字の1から末尾の2つ手前の要素までのリストを抽出
print extr_s1
extr_n3 = num1[1:6:2] # 1から5まで2つとびのリストを抽出
print extr_n3
extr_n4 = num1[1:6]
print extr_n4
print
# リストの連結
cmbn = num1 + num2 # 2項演算子'+'で連結
print cmbn
cmbs = str1 + str2
print cmbs
cmbhy = num1 + str1 # 中の要素が異なっていてもOK
print cmbhy
print
# リストの連結(データ型を文字列に変更)(文字列のメソッド)
print cmbs
ch = ','
cmb1 = ch.join(cmbs) # joinの引数にはstring要素のリストを。cmbnだとエラー
print type(cmb1)
print cmb1
print
# リストに要素の追加(注:データそのものを書き換える)
num3 = [1100, 1130, 1255, 1300]
print num3
num3.append(3)
print num3
str3 = ['hi', 'hello', 'hey', 'bye', 'ya']
print str3
str3.append('Yap')
print str3
print
12
255
[1, 4, 7, 12, 23]
[7, 12, 23, 41, 88, 96]
['hello', 'hey']
[4, 12, 41]
[4, 7, 12, 23, 41]
[1, 4, 7, 12, 23, 41, 88, 96, 100, 130, 255, 1000]
['Jon', 'Mery', 'Sun', 'Ren', 'hi', 'hello', 'hey', 'bye', 'ya']
[1, 4, 7, 12, 23, 41, 88, 96, 'Jon', 'Mery', 'Sun', 'Ren']
['Jon', 'Mery', 'Sun', 'Ren', 'hi', 'hello', 'hey', 'bye', 'ya']
<type 'str'>
Jon,Mery,Sun,Ren,hi,hello,hey,bye,ya
[1100, 1130, 1255, 1300]
[1100, 1130, 1255, 1300, 3]
['hi', 'hello', 'hey', 'bye', 'ya']
['hi', 'hello', 'hey', 'bye', 'ya', 'Yap']
#!/usr/bin/python
# coding: UTF-8
# リストの初期化
numbers = [1, 4, 7, 12, 23]
strings = ['Jon', 'Mery', 'Sun', 'Ren']
empty = [] # 空リスト
inilist = [0] * 4 # 0で初期化された要素が4つのリスト
# 型は?
print type(numbers)
print type(strings)
print type(empty)
print
# リストの全ての要素を表示
print numbers
print strings
print empty
print inilist
print
# for文で全要素を表示
for i in range(len(numbers)): # lenでリストの要素数を求める, rangeにループ回数(回数分の要素のリストが戻り値), inはリストをとる
print '%d, ' % (numbers[i]), # print文の末尾に「,」を付けると改行しない
print '\n'
# リストの要素の1つを表示
print numbers[0] # 要素は0から始まる
print numbers[3]
print strings[-1] # 最末尾の要素
print strings[-3]
print
# リスト要素に代入
numbers[2] = 1000
strings[1] = 'Micky'
# 代入の確認
print numbers[2]
print strings[1]
<type 'list'>
<type 'list'>
<type 'list'>
[1, 4, 7, 12, 23]
['Jon', 'Mery', 'Sun', 'Ren']
[]
[0, 0, 0, 0]
1, 4, 7, 12, 23,
1
12
Ren
Mery
1000
Micky