Python独習!

習得したPython知識をペイフォワード

Pythonで二重ループ(for文の入れ子)の内包表記

他人のコードを見ていると2重ループが内包表記で記述されていることがある。
リストの要素を頻度順に並び変えるプログラムを考えていて、また見かけたのでこれを機に使い方を勉強した。

題材となるプログラムは、入力に対して以下のように出力がほしい。

入力:['c', 'c', 'b', 'd', 'c', 'b', 'a', 'b', 'e']
出力:['c', 'c', 'c', 'b', 'b', 'b', 'd', 'a', 'e']


プログラムはこんな感じになるかと。
Case1は自分で考えたもの。難産だった。
Case2は他人さまのコードを参考に、for文の入れ子で記述したもの。
Case3はCase2を内包表記で書いたもの。

from collections import Counter as cont

def case1(dataset):
    s_dataset = cont(dataset).most_common()
    result = []
    for i in range(len(s_dataset)):
        for j in range(s_dataset[i][1]):
            result.append(s_dataset[i][0])
    return result

def case2(dataset):
    result = []
    for k, v in cont(dataset).most_common():
        for i in [k] * v:                       # ['a'] * 3 = ['a', 'a', 'a']
            result.append(i)
    return result

def case3(dataset): # showing case2 in a way of list comprehensitions
    return [i for k, v in cont(dataset).most_common() for i in [k] * v]

if __name__ == "__main__":

    dataset = ['c', 'c', 'b', 'd', 'c', 'b', 'a', 'b', 'e']

    print("case1_result ->", case1(dataset))
    print("case2_result ->", case2(dataset))
    print("case3_result ->", case3(dataset))


実行結果は以下の通り。

case1_result -> ['c', 'c', 'c', 'b', 'b', 'b', 'd', 'a', 'e']
case2_result -> ['c', 'c', 'c', 'b', 'b', 'b', 'd', 'a', 'e']
case3_result -> ['c', 'c', 'c', 'b', 'b', 'b', 'd', 'a', 'e']
/* -----codeの行番号----- */