PHPしか知らない僕がPythonを少し触ってみたよ 〜リストをいじくり回す2〜

この記事はだいぶ前に書かれたものなので情報が古いかもしれません
手首のスペルは「wrist」です

この記事を三行にまとめると

ラジバンダリしてみたいと思います
デフォルトでnatsortできる機能はないらしい
手首(リスト)のスペルはwrist
今回もリストについてです。要素の数を数えたり任意の文字で連結してみたりソートしてみたりラジバンダリしてみたいと思います。



要素の数を数える

リストの中に要素がいくつあるか。

//PHP
$array = array('a', 'b', 'c', 'd', 'e');
$count = count($array);

#Python
array = ['a', 'b', 'c', 'd', 'e']
count = len(array)

Pythonにも「count()」はあるのですが、あれは要素の数を数えるものではないので混乱しないようにしたいですね。



指定した要素の数を数える

Pythonの「count()」は指定した要素がリストの中にいくつあるかを返してくれる関数です。PHPにも「array_count_values()」というのがありますが、ちょっと動きが違うので両方見てみましょう。

リストの中に「a」という要素がいくつあるのか取得する場合を考えます。

//PHP
$array = array('a', 'a', 'a', 'b', 'b', 'c');
$count = array_count_values($array);

//出力結果
Array([a] => 3 [b] => 2 [c] => 1)

#Python
array = ['a', 'a', 'a', 'b', 'b', 'c']
count = array.count('a')

#出力結果
3

PHPの場合、配列の中にある各要素の数が配列で返ってきます。要素をキーとした配列が返ってくるので、aがいくつあるかを知りたければ「$count[‘a’]」で取れます。Pythonの方は指定した要素の数が数字で返ってきます。



要素を任意の文字で連結

リストの要素を任意の文字で連結します。PHPで言うと「implode()」ですね。

//PHP
$array = array('a', 'b', 'c', 'd', 'e');
$string = implode(',', $array);

#Python
array = ['a', 'b', 'c', 'd', 'e']
string = ','.join(array)

出力結果はいずれも「a,b,c,d,e」となります。Pythonの場合は「’連結したい文字’.join(リスト)」という書き方になります。

空文字も指定できます。

//PHP
$array = array('a', 'b', 'c', 'd', 'e');
$string = implode('', $array);

#Python
array = ['a', 'b', 'c', 'd', 'e']
string = ''.join(array)



文字列を任意の文字でリストに分割

今度は「implode()」の逆の「explode()」をやってみます。

//PHP
$string = 'a,b,c,d,e';
$array = explode(',', $string);

#Python
string = 'a,b,c,d,e'
array = string.split(',')

「join()」や[split()」はjavascriptの書き方に似てますね。javascriptを書く人には馴染みやすいかも。



配列の要素の合計

要素の数ではなく、要素の数字を全部足した合計を知りたい場合。

//PHP
$array = array(1, 2, 3, 4, 5);
$total = array_sum($array);

#Python
array = [1, 2, 3, 4, 5]
total = sum(array)

型には注意です。Pythonは文字列型だと数字であっても「sum()」が使えません。

#エラーになる
array = ['1', '2', '3', '4', '5']
sum(array)



全ての要素に同一の処理を行う

同一の処理を行うって言い方が適当なのか分からないのですが、ようはPHPの「array_map()」です。

今回はリストの要素を二倍してみます。

//PHP
function twice($n) {
  return $n * 2;
}

$array = array(1, 2, 3, 4, 5);
$array = array_map('twice', $array);

#Python
def twice(n):
  return n * 2

array = [1, 2, 3, 4, 5]
array = map(twice, array)

基本的な書き方は一緒ですがコールバック関数の書き方がちょい違います。PHPはコーテーションをつけるのに対してPythonはつけません。互いに逆の書き方をするとエラーになります。

上記の処理を行えばarrayの中身が[2,4,6,8,10]になります。ただし型がリスト型ではなくなってしまうので、たとえば「array[0]」とかで値を取得したい場合はリスト型に直す必要があります。

def twice(n):
  return n * 2

array = [1, 2, 3, 4, 5]
array = map(twice, array)
array = list(array)
print(array[0])



要素を逆にする

「a,b,c,d,e」を「e,d,c,b,a」みたいに逆にする方法です。

//PHP
$array = array('a','b','c','d','e');
$array = array_reverse($array);

#Python
array = ['a', 'b', 'c', 'd', 'e']
array.reverse()



昇順・降順に並べる

ソートです。昇順ってのは数字だと値の小さい方から、文字列だとアルファベット順や五十音順ってことです。降順はその逆。

まずは昇順から。

//PHP
$array = array(1, 100, 101, 10, 11);
sort($array);

#Python
array = [1, 100, 101, 10, 11]
array.sort()

これで「1,10,11,100,101」という順番に並び替えられます。

続いて降順。

//PHP
$array = array(1, 100, 101, 10, 11);
rsort($array);

#Python
array = [1, 100, 101, 10, 11]
array.sort(reverse = True)

Pythonは昇順も降順もどちらも同じ「sort()」という関数を使います。降順にする場合は「reverse」というパラメータで指定する。



Pythonの場合、「sorted()」という書き方もあります。結果は一緒。

#昇順
array = [1, 100, 101, 10, 11]
array = sorted(array)

#降順
array = [1, 100, 101, 10, 11]
array = sorted(array, reverse = True)



自然順について

気をつけたいのは、要素が数値型だとちゃんと数字の小さい方から並ぶのですが、文字列型として扱った場合は必ずしもそうなるとは限りません。

array = ['1', '100', '101', '10', '11']
array.sort()

#出力結果
['1', '10', '100', '101', '11']

PHPは型がゆるいのでコーテーションをつけても数字として処理してくれますが、Pythonだとそうはいきません。コーテーションをつけると数字も単なる文字列として扱われるので、上記のような場合、「11」よりも「100」とか「101」の方が先に来る。文字列的には1よりも0の方が前だからです。

PHPでも、例えばアルファベットと数字を組み合わせた文字列とかだと同様の現象が起こります。

$array = array('a1','a10','a11','a100','a101');
sort($array);

//出力結果
Array([0] => a1 [1] => a10 [2] => a100 [3] => a101 [4] => a11)

Pythonの時と同じように「a100」や「a101」が「a11」よりも前に来てますね。

これを数字の小さい方から並べるには自然順にソートする必要があります。自然順ってのは僕たち人間が考えるような順番のことで、自然順にソートすれば文字列が入っていようが何だろうが僕たちが意図する昇順にできます。

PHPで自然順にソートするには「natsort()」という関数を使います。

//PHP
$array = array('a1','a10','a11','a100','a101');
natsort($array);

//出力結果
Array([0 => a1 [1] => a10 [2] => a11 [3] => a100 [4] => a101)

文字列が入っていてもちゃんと数値の小さい方から並んでいますね。

同じことがPythonでも簡単に実現できれば良いのですが、どうも一筋縄ではいかないみたいです。Pythonではデフォルトでnatsortできる機能がないらしい。こういう(↓)モジュールを入れるとかしないとダメみたいっす。

https://pypi.python.org/pypi/natsort

実際に検証はしてないので使い方については今回は省略です。申し訳ない。



キーの昇順・降順

要素ではなく添字やキーでソートする場合。PHPの「ksort()」や「krsort()」ですね。

//PHP
$array = array(1, 100, 101, 10, 11);
ksort($array); //昇順
krsort($array); //降順

#Python
array = [1, 100, 101, 10, 11]
array = sorted(array, key = array.index) #昇順
array = sorted(array, key = array.index, reverse = True) #降順

「sorted()」はreverseの他に「key」というパラメータもあります。keyを指定するとその順番でソートできます。上記の場合はリストのインデックスを指定しているので「ksort()」と同じ動きになるわけです。

まあ、単純なリストの場合だと最初からインデックス順に並んでますから「ksort()」を使っても中身は特に変わらないし、「krsort()」も「array.reverse()」を使えば良いんですけど、こういう書き方もあるってことを知っとくと役立つこともあるかもしれない。

例えばこんな時(↓)とか。



重複した要素を削除する

前回やり逃した重複した要素を削除する方法です。PHPの「array_unique()」

//PHP
$array = array('a', 'a', 'a', 'b', 'b', 'c');
$array = array_unique($array);

#Python
array = ['a', 'a', 'a', 'b', 'b', 'c']
array = set(array)

PHPの「array_unique()」との違いは、削除後に型がリスト型からセット型に変わってしまうことと、順番も変わってしまうことがある点です。「array_unique()」なら上記の場合は必ず「a,b,c」の順番になりますが、「set()」の方は「b,a,c」の順になることもあれば「c,a,b」になることもある。「a,b,c」のままのこともある。

この順番を保持したい場合は、さっきのインデックス順のソートを組み合わせます。

array = ['a', 'a', 'a', 'b', 'b', 'c']
array = sorted(set(array), key = array.index)

もちろん「reverse = True」も合わせれば「c,b,a」の順番を保持できます。

ちなみにこっちのやり方だと型も変わりません。リスト型のままです。






こんなとこでしょうか。僕は普段、ソートはあまり使いませんが、implode()やexplode()、array_unique()あたりはちょいちょい使うので、Pythonで開発する日がくればこの辺りは多用するかもしれない。

それにしても、PHPを覚えたての頃に先輩プログラマーから「PHPは配列地獄だぜ」って言われたことがあったんですけど、Pythonもそれは変わらないんでしょうね。

配列を制するものはプログラムを制す……?



その他のPythonを少し触ってみたの記事はこちら
前書きと索引的な
 もしかしたら何か関連しているかも? 
 質問や感想などお気軽にコメントしてください