リスト内包表記


リスト内包表記で一時変数を使用したいがために無駄なforループを1つ増やしているということだが、問題点は以下の3つ。

  • 式しか書けないので代入文が書けない
  • sys.stdinから読み取ってsplitしたやつで回したいのに、2段階に分けないといけない
  • 式が1つしか書けないので、初期化したり、途中で代入したりする場所がない


1つ目は、書き方は汚いが代入文を式に変換する方法がある。2つ目は、__iter__をオーバーライドする方法がある。もしくは一時変数に保存しておけば良い。3つ目は、ifの後や結果の式中に無理やり書ける。


以下2通りの方法を考えたが、いずれも汚い。結局、きれいに書くにはPythonのポリシー通り内包表記でなくfor文で普通に書くしか思いつかない...。我ながら勉強不足。以下はコード断片。

NFOアプローチ版。

import sys

def foo():pass
[foo.kv[1] for line in sys.stdin if setattr(foo, 'kv', line.split()) or foo.kv[0] in tags]

__iter__をオーバーライド版。

import sys
from StringIO import *

class file2(StringIO):
    def __iter__(self):
        while True:
            line = self.next()
            yield line.split()
       
[v for k, v in file2(sys.stdin.read()) if k in tags]

このケースでは不可能だが、似た問題の別のアプローチは私の過去の日記で作成したflatten_forで複数ループを1重ループに落とし込む方法とか。permutationという関数名でitertoolsもしくはビルトインに入れて欲しいなあ。

PyBuilder

py2exeのGUI版PyBuilderは使用したことないがpy2exe単体で何の不満もないのでとりあえず試してみたことない。何やらうまくいかない場合もあるようでとりあえず保留。Pythonはシンプルだけど周辺ライブラリ、ツールが多すぎて、1つのやりたい事に対するやり方が1つではなくなっている。今後はますますすぐれた書籍やドキュメントが重要。

"汎用配列を作成します"エラーと戯れる

import java.util.Arrays;
import java.util.LinkedHashSet;

public class Unique {
    public static Object[] toUniqueArray(Object[] array) {
        return new LinkedHashSet(Arrays.asList(array)).toArray();
    }
}

勉強のためこれをGenerics化しようと思った。Collectionオブジェクト を T toArray(T a) を使って配列に変換しようとしたときに toArray(new T[0]) で表題のエラーが出た。回避方法をググって以下に落ち着いた。

import java.util.Arrays;
import java.util.LinkedHashSet;
import java.lang.reflect.Array;

public class test {
    public static <T> T[] toUniqueArray(T[] arr) {
        T[] t = (T[])Array.newInstance(arr.getClass().getComponentType(), 0);
        return new LinkedHashSet<T>(Arrays.asList(arr)).toArray(t);
    }
    public static void main(String[] args) {
        Integer[] arr = test.toUniqueArray(new Integer[]{4, 1, 2, 2, 3, 4, 2, 8});
        System.out.println(Arrays.asList(arr));
    }
}

# 実行結果
[4, 1, 2, 3, 8]

これはちょろっと書きたいときに書けない方法である。かと言って T でなく Object を使用するのもどうかと思う。この辺の設計を実戦ではどうすべきかは非常に悩む。つまり配列とコレクションクラスをどう使い分けるか。Javaの達人がいたら教えて欲しい。ワイルドカードを使用すればさらに完璧になると思うが、それに関しては後日調べるつもり。


コレクションクラスはGenericsが入ってきてかなり敷居が高くなったのでJavaに力を入れて勉強するつもり。Javaの勉強ページも作成しようかな。以下はかなり参考になった。