2017-08-30 7 views
5

मैं एक लेखा पेड़ है कि स्रोत में इंडेंट/रिक्तियों के साथ संग्रह किया गया है के आधार पर पदानुक्रम पार्स करने के लिए कैसे:अजगर के साथ इंडेंट

Income 
    Revenue 
     IAP 
     Ads 
    Other-Income 
Expenses 
    Developers 
     In-house 
     Contractors 
    Advertising 
    Other Expenses 

स्तरों की एक निश्चित संख्या में हैं, इसलिए मैं समतल करना चाहते हैं

for rownum in range(6,ws.max_row+1): 
    accountName = str(ws.cell(row=rownum,column=1).value) 
    indent = len(accountName) - len(accountName.lstrip(' ')) 
    if indent == 0: 
     l1 = accountName 
     l2 = '' 
     l3 = '' 
    elif indent == 3: 
     l2 = accountName 
     l3 = '' 
    else: 
     l3 = accountName 

    w.writerow([l1,l2,l3]) 
:

L1  L2   L3 
Income 
Income Revenue 
Income Revenue  IAP 
Income Revenue  Ads 
Income Other-Income 
Expenses Developers In-house 
... etc 

मैं खाता नाम से पहले स्थानों की संख्या की जाँच करके ऐसा कर सकते हैं: 3 क्षेत्रों का उपयोग करके पदानुक्रम (वास्तविक डेटा 6 स्तर, उदाहरण के लिए सरल बनाया गया है)

क्या यह पिछले पंक्ति की तुलना में वर्तमान पंक्ति के इंडेंटेशन के आधार पर इसे प्राप्त करने के लिए एक और अधिक लचीला तरीका है, यह मानते हुए कि यह हमेशा 3 रिक्त स्थान प्रति स्तर है? L1 में हमेशा कोई इंडेंट नहीं होगा, और हम भरोसा कर सकते हैं कि निचले स्तर को उनके माता-पिता से आगे इंडेंट किया जाएगा, लेकिन शायद प्रति स्तर 3 स्पेस नहीं हो सकता है।

अद्यतन, तर्क के मांस के रूप में इसके साथ समाप्त हुआ, क्योंकि आखिरकार मैं सामग्री के साथ खाता सूची चाहता था, यह तय करने के लिए इंडेंट का उपयोग करना आसान था कि सूची को रीसेट, संलग्न या पॉप करना है:

 if indent == 0: 
      accountList = [] 
      accountList.append((indent,accountName)) 
     elif indent > prev_indent: 
      accountList.append((indent,accountName)) 
     elif indent <= prev_indent: 
      max_indent = int(max(accountList,key=itemgetter(0))[0]) 
      while max_indent >= indent: 
       accountList.pop() 
       max_indent = int(max(accountList,key=itemgetter(0))[0]) 
      accountList.append((indent,accountName)) 

तो आउटपुट की प्रत्येक पंक्ति पर खातासूची पूरी हो गई है।

उत्तर

4

आप पाइथन वास्तव में इंडेंटेशन को पार करने के तरीके की नकल कर सकते हैं। सबसे पहले, एक स्टैक बनाएं जिसमें इंडेंटेशन स्तर होंगे। प्रत्येक पंक्ति में:

  • तो खरोज ढेर के शीर्ष से भी बड़ा है, यह धक्का और गहराई स्तर को बढ़ाने के।
  • यदि यह वही है, तो उसी स्तर पर जारी रखें।
  • यदि यह कम है, तो स्टैक के शीर्ष पर पॉप करें जबकि यह नए इंडेंटेशन से अधिक है। यदि आपको बिल्कुल वही ढूंढने से पहले निचला इंडेंटेशन स्तर मिलता है, तो एक इंडेंटेशन त्रुटि होती है।
indentation = [] 
indentation.append(0) 
depth = 0 

f = open("test.txt", 'r') 

for line in f: 
    line = line[:-1] 

    content = line.strip() 
    indent = len(line) - len(content) 
    if indent > indentation[-1]: 
     depth += 1 
     indentation.append(indent) 

    elif indent < indentation[-1]: 
     while indent < indentation[-1]: 
      depth -= 1 
      indentation.pop() 

     if indent != indentation[-1]: 
      raise RuntimeError("Bad formatting") 

    print(f"{content} (depth: {depth})") 

एक "test.txt" फ़ाइल जिनकी सामग्री के साथ है के रूप में आपके द्वारा दी गई:

Income (depth: 0) 
Revenue (depth: 1) 
IAP (depth: 2) 
Ads (depth: 2) 
Other-Income (depth: 1) 
Expenses (depth: 0) 
Developers (depth: 1) 
In-house (depth: 2) 
Contractors (depth: 2) 
Advertising (depth: 1) 
Other Expense (depth: 1) 

तो, क्या कर सकते हैं:

Income 
    Revenue 
     IAP 
     Ads 
    Other-Income 
Expenses 
    Developers 
     In-house 
     Contractors 
    Advertising 
    Other Expenses 

यहाँ उत्पादन होता है आप इसके साथ करते हो मान लीजिए कि आप नेस्टेड सूचियां बनाना चाहते हैं। सबसे पहले, डेटा स्टैक बनाएं।

  • जब आपको इंडेंटेशन मिलता है, तो डेटा स्टैक के अंत में एक नई सूची संलग्न करें।
  • जब आप एक अनइंडेंटेशन पाते हैं, तो शीर्ष सूची पॉप करें, और इसे नए शीर्ष पर जोड़ें।

और प्रत्येक लाइन के लिए, डेटा स्टैक के शीर्ष पर सामग्री को सामग्री में शामिल करें।

for line in f: 
    line = line[:-1] 

    content = line.strip() 
    indent = len(line) - len(content) 
    if indent > indentation[-1]: 
     depth += 1 
     indentation.append(indent) 
     data.append([]) 

    elif indent < indentation[-1]: 
     while indent < indentation[-1]: 
      depth -= 1 
      indentation.pop() 
      top = data.pop() 
      data[-1].append(top) 

     if indent != indentation[-1]: 
      raise RuntimeError("Bad formatting") 

    data[-1].append(content) 

while len(data) > 1: 
    top = data.pop() 
    data[-1].append(top) 

आपका नेस्टेड सूची अपने data ढेर के शीर्ष पर है:

यहाँ इसी कार्यान्वयन है। एक ही फ़ाइल के लिए आउटपुट है:

['Income', 
    ['Revenue', 
     ['IAP', 
     'Ads' 
     ], 
    'Other-Income' 
    ], 
'Expenses', 
    ['Developers', 
     ['In-house', 
     'Contractors' 
     ], 
    'Advertising', 
    'Other Expense' 
    ] 
] 

इस बल्कि हेरफेर करने के लिए आसान है, हालांकि काफी गहरा नेस्ट। आप आइटम चेनिंग से डेटा का उपयोग कर सकते हैं तक पहुँचता है: खरोज रिक्त स्थान की एक निश्चित राशि (यहाँ 3 रिक्त स्थान) है

>>> l = data[0] 
>>> l 
['Income', ['Revenue', ['IAP', 'Ads'], 'Other-Income'], 'Expenses', ['Developers', ['In-house', 'Contractors'], 'Advertising', 'Other Expense']] 
>>> l[1] 
['Revenue', ['IAP', 'Ads'], 'Other-Income'] 
>>> l[1][1] 
['IAP', 'Ads'] 
>>> l[1][1][0] 
'IAP' 
+0

इस के लिए धन्यवाद, मैं अंत में उत्पादन करने में सक्षम होना चाहते थे लाइन की सामग्री के साथ-साथ प्रत्येक पंक्ति में पदानुक्रम, तो मैं थोड़ा संशोधित, लेकिन यह मुझे सही दिशा में शीर्षक मिला। –

2

हैं, तो आप खरोज स्तर की गणना को आसान बनाने में कर सकते हैं।

ध्यान दें: मैं एक StringIO का उपयोग एक फ़ाइल अनुकरण

import io 
import itertools 

content = u"""\ 
Income 
    Revenue 
     IAP 
     Ads 
    Other-Income 
Expenses 
    Developers 
     In-house 
     Contractors 
    Advertising 
    Other Expenses 
""" 

stack = [] 
for line in io.StringIO(content): 
    content = line.rstrip() # drop \n 
    row = content.split(" ") 
    stack[:] = stack[:len(row) - 1] + [row[-1]] 
    print("\t".join(stack)) 

आप मिल:

Income 
Income Revenue 
Income Revenue IAP 
Income Revenue Ads 
Income Other-Income 
Expenses 
Expenses Developers 
Expenses Developers In-house 
Expenses Developers Contractors 
Expenses Advertising 
Expenses Other Expenses 

संपादित करें: खरोज तय नहीं

खरोज नहीं है, तो निश्चित (आपके पास हमेशा 3 रिक्त स्थान नहीं होते हैं) जैसे नीचे दिए गए उदाहरण में:

content = u"""\ 
Income 
    Revenue 
    IAP 
    Ads 
    Other-Income 
Expenses 
    Developers 
     In-house 
     Contractors 
    Advertising 
    Other Expenses 
""" 

आप प्रत्येक नई लाइन पर स्थानांतरण आकलन करने की जरूरत:

stack = [] 
last_indent = u"" 
for line in io.StringIO(content): 
    indent = "".join(itertools.takewhile(lambda c: c == " ", line)) 
    shift = 0 if indent == last_indent else (-1 if len(indent) < len(last_indent) else 1) 
    index = len(stack) + shift 
    stack[:] = stack[:index - 1] + [line.strip()] 
    last_indent = indent 
    print("\t".join(stack)) 
संबंधित मुद्दे