PostgreSQL consente di creare indici su espressioni, ad esempio CREATE INDEX ON films ((lower(title)))
. Ha anche una funzione di informazione pg_get_expr()
che traduce il formato interno dell'espressione in testo, ad esempio, lower(title)
nell'esempio precedente. Le espressioni possono diventare piuttosto pelose a volte. Ecco alcuni esempi (in Python):Dividere l'elenco di espressioni di funzione possibilmente nidificate in 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)']
L'ultimo elemento non è davvero da Postgres, ma è solo un esempio estremo di ciò che il mio codice dovrebbe gestire.
Ho scritto una funzione Python per dividere le liste di testo nelle espressioni componente. Ad esempio, tale elemento è suddiviso in:
f1(f2(arga, f3()), arg1)
f4(arg2, f5(argb, argc))
f6(arg3)
ho sperimentato con str
metodi come find()
e count()
e regex anche considerati, ma alla fine ho scritto una funzione che è quello che avrei scritto in C (essenzialmente contando i parenti aperti e chiusi per trovare dove rompere il testo). Ecco la funzione:
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
La domanda è se c'è un altro Pythonic o modo elegante per fare questo o di usare espressioni regolari per risolvere questo.
Dai un'occhiata alla [ pyparsing] (http://pyparsing.wikispaces.com/) per qualche ispirazione –
I regexes potrebbero non avere nulla di elegante. Vedi: http://perldoc.perl.org/perlfaq6.html#Can-I-use-Perl-regular-expressions-to-match-balanced-text%3f – Himanshu
Sì, mi sono convinto che le regex non possono essere usato perché le macchine di stato non possono contare l'annidamento di parentesi senza l'aiuto di una pila, cioè è necessario un PDA. –