2012-10-16 16 views
5

में संभवतः नेस्टेड फ़ंक्शन एक्सप्रेशन की विभाजन सूची पोस्टग्रेएसक्यूएल इंडेक्स को अभिव्यक्तियों पर बनाने की अनुमति देता है, उदाहरण के लिए, CREATE INDEX ON films ((lower(title)))। इसमें pg_get_expr() सूचना फ़ंक्शन भी है जो अभिव्यक्ति के आंतरिक स्वरूप को पाठ में संदर्भित करता है, यानी, उदाहरण के लिए lower(title)। अभिव्यक्ति कई बार काफी बालों वाली हो सकती है। यहाँ (अजगर में) कुछ उदाहरण हैं:पायथन

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 से नहीं है, लेकिन सिर्फ मेरे कोड को संभालने के लिए चाहिए का एक चरम उदाहरण है।

मैंने पाठ अभिव्यक्तियों को पाठ अभिव्यक्तियों में विभाजित करने के लिए एक पायथन फ़ंक्शन लिखा था। उदाहरण के लिए, कि पिछले आइटम में बांटा गया है:

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

मैं find() और count() तरह str तरीके और भी विचार regexes के साथ प्रयोग किया, लेकिन अंत में मैं एक समारोह में लिखा है कि मैं क्या (सी में लिखा है | पाठ को तोड़ने के लिए यह जानने के लिए अनिवार्य रूप से खुले और करीबी माता-पिता की गिनती)। यहाँ समारोह है:

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 या सुरुचिपूर्ण तरीका है कि क्या वहाँ यह करने के लिए या इसे सुलझाने के लिए regexes उपयोग करने के लिए है।

+1

पर एक नज़र डालें नहीं दिख रहा है [ पाइपर्सिंग] (http://pyparsing.wikispaces.com/) कुछ प्रेरणा के लिए –

+0

रेगेक्स में कुछ भी सुरुचिपूर्ण नहीं हो सकता है। देखें: http://perldoc.perl.org/perlfaq6.html#Can-I-use-Perl-regular-expressions-to-match-balanced-text%3f – Himanshu

+0

हां, मैं आश्वस्त हो गया हूं कि regexes नहीं कर सकते इस्तेमाल किया जाना चाहिए क्योंकि राज्य-मशीन एक ढेर की मदद के बिना कोष्ठक के घोंसले की गणना नहीं कर सकते हैं, यानी, पीडीए आवश्यक है। –

उत्तर

1

यदि आप इसे और अधिक पाइथनिक बनाना चाहते हैं, तो मुझे लगता है कि एकमात्र तरीका पठनीयता है।

इसके अतिरिक्त मैं ढेर की गणना करके एक शाखा और एक चर से बचता हूं। एकमात्र पायथन सुझाव जो मैं दे सकता हूं वह 'सूचकांक' चर का उपयोग enumerate(...) फ़ंक्शन के साथ करना है।

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)) 
+0

एकल stack_level चर निश्चित रूप से एक सुधार है। हालांकि, रेंज (लेन (एफएनएस)) मुझे पाइथोनिक के रूप में नहीं रोकती है, और मुझे नहीं पता कि प्रत्येक चरित्र को एफएनएस [curr_pos] के रूप में एक्सेस करना अधिक कुशल है (मेरा वृत्ति नहीं कहता है, लेकिन मैंने इसे बेंचमार्क नहीं किया है) । –

+0

@ जोएबेट 'रेंज (लेन ())' मेरे अनुभव में, पायथन में अविश्वसनीय रूप से असामान्य नहीं है। और आप सही हैं, 'fns [curr_pos] 'कुशल नहीं है। मैं जवाब – jsvk

1

यहाँ मेरी संस्करण, अधिक pythonic, कम अव्यवस्था मुझे लगता है कि है, और वर्ण की धारा पर काम करता है, हालांकि मुझे लगता है कि किसी भी लाभ :)

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] 
+0

संपादित कर दूंगा, मैं पार्श्व सोच से प्रभावित हूं, हालांकि एक बात पर विचार करना चाहिए: ढेर के बाहर के पात्रों के लिए, 2-5 तुलना किए जाते हैं, 2-3 यदि वे प्रतीक हैं। 2-4 कोष्ठक के लिए, और 4 कार्य निर्धारित करने के लिए पूरा हो गया है। उदाहरण के लिए, मेरा, संख्या 2, 2, 1-2, और 5-7 (संभवतः 4 बुद्धिमानी से फिर से लिखा गया है) – jsvk

+0

@jsvk मुझे लगता है कि गति स्पष्टता से अधिक मानना ​​मानदंड है, अन्यथा मैं लिखूंगा यह सी –

+0

में गति से कुशल कोड लिखने के अधिक कारण हैं, लेकिन मैं देखता हूं कि आप कहां से आ रहे हैं; स्पष्टता पाइथोनिक होने का एक महत्वपूर्ण हिस्सा है। – jsvk

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^