5

PostgreSQL では、式でインデックスを作成できますCREATE INDEX ON films ((lower(title)))。また、前の例のようにpg_get_expr()、式の内部形式をテキストに変換する情報関数もあります。lower(title)表情は時々かなり毛むくじゃらになることがあります。以下にいくつかの例を示します (Python の場合):

sample_exprs = [
    'lower(c2)',
    'lower(c2), lower(c3)',
    "btrim(c3, 'x'::text), lower(c2)",
    "date_part('month'::text, dt), date_part('day'::text, dt)",
    '"substring"(c2, "position"(c2, \'_begin\'::text)), "substring"(c2, "position"(c2, \'_end\'::text))',
    "(((c2)::text || ', '::text) || c3), ((c3 || ' '::text) || (c2)::text)",
    'f1(f2(arga, f3()), arg1), f4(arg2, f5(argb, argc)), f6(arg3)']

最後の項目は実際には Postgres のものではありませんが、私のコードが処理すべきものの極端な例です。

テキスト リストをコンポーネント式に分割する Python 関数を作成しました。たとえば、最後の項目は次のように分類されます。

 f1(f2(arga, f3()), arg1)
 f4(arg2, f5(argb, argc))
 f6(arg3)

strのようなメソッドを試し、正規表現も検討しましたが、最終的には、C で記述したであろう関数を記述しました (基本的には、開きかっこと閉じかっこを数えて、テキストを分割する場所を見つけます)。関数は次のとおりです。find()count()

def split_exprs(idx_exprs):
    keyexprs = []
    nopen = nclose = beg = curr = 0
    for c in idx_exprs:
        curr += 1
        if c == '(':
            nopen += 1
        elif c == ')':
            nclose += 1
            if nopen > 0 and nopen == nclose:
                if idx_exprs[beg] == ',':
                    beg += 1
                if idx_exprs[beg] == ' ':
                    beg += 1
                keyexprs.append(idx_exprs[beg:curr])
                beg = curr
                nopen = nclose = 0
    return keyexprs

問題は、これを行うためのよりPythonicまたはエレガントな方法があるかどうか、または正規表現を使用してこれを解決するかどうかです。

4

2 に答える 2

1

これが私のバージョンで、よりpythonicで、混乱が少ないと思いますが、 chars のストリームで動作しますが、その利点は見られません:)

def split_fns(fns):
    level = 0
    stack = [[]]
    for ch in fns:
        if level == 0 and ch in [' ',',']:
            continue        
        stack[-1].append(ch)

        if ch == "(":
            level += 1
        elif ch == ")":
            level -= 1
            if level == 0:
                stack.append([])

    return ["".join(t) for t in stack if t]
于 2012-10-18T19:30:34.013 に答える
1

より Pythonic にしようとしている場合、私が考えることができる唯一の方法は読みやすさです。

さらに、スタックをカウントすることで、1 つのブランチと 1 つの変数を回避します。私ができる唯一のpythonicの提案は、enumerate(...)関数で「index」変数を使用することです。のように

for i, j in enumerate(<iterable>)

これによりi、現在のループ番号に等しい変数 が作成されます。ここでj、 は予想される反復変数になります。

def split_fns(fns):
    paren_stack_level = 0
    last_pos = 0
    output = []
    for curr_pos, curr_char in enumerate(fns):
        if curr_char == "(":
            paren_stack_level += 1
        elif curr_char == ")":
            paren_stack_level -= 1
            if not paren_stack_level:
                output.append( fns[last_pos:curr_pos+1].lstrip(" ,") )
                last_pos = curr_pos+1
    return output

for i in sample_exprs:
    print(split_fns(i))
于 2012-10-17T06:55:39.620 に答える