tests = ['A,B,C', 'D,E', 'A,C,E']
のようなデータがあったとき
これを要素別に
'A,B,C'
-> ('A','B'),('A','C'),('B','C')
'D,E'
-> ('D','E')
'A,C,E'
-> ('A','C'),('A','E'),('C','E')
にしたい。
つまり以下のようにしたい。
[('A', 'B'),
('A', 'C'),
('B', 'C'),
('D', 'E'),
('A', 'C'),
('A', 'E'),
('C', 'E')]
要求を整理すると、tests
の変数において、
- 各要素を配列にする
- 2つの組み合わせにする
をする方法をまとめる。
一行で書くと以下のようになる
list(itertools.chain.from_iterable([tuple(itertools.combinations(tuple(i.split(",")), 2)) for i in tests if len(i.split(",")) > 1]))
解説
各要素を配列にする
[tuple(i.split(",")) for i in tests if len(i.split(",")) > 1]
# -> [('A', 'B', 'C'), ('D', 'E'), ('A', 'C', 'E')]
i.split(",")
により要素1の配列しかできないものは、後続の処理で弾かれるためこの時点で弾いておく。
2つの組み合わせにする
[tuple(itertools.combinations(tuple(i.split(",")), 2)) for i in tests if len(i.split(",")) > 1]
# -> [(('A', 'B'), ('A', 'C'), ('B', 'C')),
# (('D', 'E'),),
# (('A', 'C'), ('A', 'E'), ('C', 'E'))]
itertools.combinationsを使用した。
この場合、リスト内包表記内で、「各要素を配列にする」の後に、itertools.combinations
関数を利用する。結果としては配列中に、tupleが入ったような形になってしまっている。
これを解決するのにさらに、itertools.chain.from_iterable
関数を利用する。(itertools.chain.from_iterable)
よって以下のようになる。
list(itertools.chain.from_iterable([tuple(itertools.combinations(tuple(i.split(",")), 2)) for i in tests if len(i.split(",")) > 1]))