2017-02-22 50 views
0

我需要從xml字段組裝一個長文本字符串。索引/偏移性能很糟糕 - 我做錯了什麼? Python

XML_FIELD_ONE = 「Iamacatthatisoddlyimmunetocatnip」

XML_FILED_TWO = [7,8,24]

FILED_TWO包含要插入任一\ n或\ r處的索引。 如果兩個索引相距1(如7,8),則需要插入\ r \ n。如果索引是獨奏(如24),我需要插入\ n。

使用此代碼處理25K行文件需要大約2分鐘的時間。 我在做什麼錯?

XML_FIELD_ONE = list("Iamacatthatisoddlyimmunetocatnip") 
XML_FILED_TWO = [7,8,24] 

idx = 0 
while idx <= len(XML_FIELD_ONE): 
    for position in XML_FIELD_ONE: 
     for space in XML_FIELD_TWO: 

      if idx == int(space) and idx+1 == int(space)+1: 
       XML_FIELD_ONE[idx] = "\r" 

         try: 
          XML_FIELD_ONE[idx+1] = "\n" 
         except: 
          pass 

       elif idx == int(space): 
       XML_FIELD_ONE[idx] = "\n" 

    idx += 1 


new_text = "".join(XML_FIELD_ONE) 
return new_text 

這樣做的簡單的方法是:

for offset in XML_FILED_TWO: 
    XML_FILED_ONE[offset] = \n 

但是這違反了 「如果兩個偏移在一起,第一個是用\ r,下一個是\ n」 個

+0

這是不相關的,但是什麼時候將'idx == int(space)'設置爲True並且'idx + 1 == int(space)+ 1'不是真的?我錯過了什麼嗎?裸體「除外」是什麼?那些不好。你想抓住一個'IndexError'嗎?通常情況下,你應該嘗試明確地處理這些問題,或者糾正你的代碼,這樣就不會發生......老實說,我很難用你的代碼來描述它的功能......你不是插入*,可以這麼說,而是取代。而3個嵌套循環似乎完全沒有必要。 –

+0

但是,爲了回答你的問題,你的算法在XML_FIELD_ONE的長度方面將是*最小*二次方,實際上,就我所知,它是O(m * n^2),其中'n = len(XML_FIELD_ONE)'和'm = len(XML_FIELD_TWO)'......似乎並不是正確的方法,因爲你描述了你正在努力完成的任務。 –

+0

該空間只有7,8,24,這意味着它不會是真實的,除非你在索引7。含義索引7和8被替換爲7和8. 裸體除了是捕捉最後一個idx錯誤,是的。當您處於MAX指數時,您無法查看MAX指數+1。 –

回答

1

你當你只需要一個時寫了一個三重循環;這是非常低效的。你確切地知道在哪裏插入新項目:直接在那裏,而不是增加兩個計數器找到的地方。

我不確定你需要插入的確切位置,但這應該很接近。爲了保持原始索引的正確性,您需要從右端插入並工作到左側;這就是我反轉XML_FIELD_TWO的原因。

我留在我的調試打印語句。

XML_FIELD_ONE = list("Iamacatthatisoddlyimmunetocatnip") 
XML_FIELD_TWO = [7,8,24] 

print XML_FIELD_ONE 
XML_FIELD_TWO = XML_FIELD_TWO[::-1] 
print XML_FIELD_TWO 
i = 0 
while i < len(XML_FIELD_TWO): 
    print i, XML_FIELD_TWO[i] 
    if XML_FIELD_TWO[i] - XML_FIELD_TWO[i+1] == 1: 
     XML_FIELD_ONE.insert(XML_FIELD_TWO[i], '\r\n') 
     i += 2 
    else: 
     XML_FIELD_ONE.insert(XML_FIELD_TWO[i], '\n') 
     i += 1 

    print "\n", ''.join(XML_FIELD_ONE) 

輸出:

['I', 'a', 'm', 'a', 'c', 'a', 't', 't', 'h', 'a', 't', 'i', 's', 'o', 'd', 'd', 'l', 'y', 'i', 'm', 'm', 'u', 'n', 'e', 't', 'o', 'c', 'a', 't', 'n', 'i', 'p'] 
[24, 8, 7] 
0 24 

Iamacatthatisoddlyimmune 
tocatnip 
1 8 

Iamacatt 
hatisoddlyimmune 
tocatnip 
+0

是的,我使用了一個for循環並記錄了插入次數,但插入反向工作也很棒! –

1

可以使用蟒enumerate()函數,以產生在單個循環索引/值對的序列。然後你可以使用list.insert(pos, val)方法來插入你想要的字符。

XML_FIELD_ONE = list("Iamacatthatisoddlyimmunetocatnip") 
XML_FIELD_TWO = [7,8,24] 

last_i = len(XML_FIELD_TWO) - 1 

for i,p in enumerate(XML_FIELD_TWO): 
    ch = '\r' if i < last_i and XML_FIELD_TWO[i+1] == p+1 else '\n' 
    XML_FIELD_ONE.insert(p, ch) 

print(XML_FIELD_ONE) 
+0

比我的「適合級別」的解決方案好得多。我希望別人從中學習。 – Prune

0

這裏是一個線性算法來實現你正在嘗試做的。其實用try-except是完全合適的位置,但你應該永遠不會有一個赤裸的,除了

>>> XML_FIELD_ONE = list("Iamacatthatisoddlyimmunetocatnip") 
>>> XML_FIELD_TWO = [7,8,24] 
>>> insertions = 0 
>>> for i, e in enumerate(XML_FIELD_TWO): 
...  try: 
...   cont = e + 1 == XML_FILED_TWO[i+1] 
...  except IndexError: 
...   cont = False 
...  if cont: 
...   XML_FI.insert(e+1+insertions, '\r\n') 
...   XML_FIELD_ONE.insert(e+1+insertions, '\r\n') 
...  else: 
...   XML_FIELD_ONE.insert(e + insertions, '\n') 
...  insertions += 1 
... 
>>> print("".join(XML_FIELD_ONE)) 
Iamacatt 

hatisoddlyimmune 
tocatnip 
>>> 

我跟蹤這抵消了.insert用來保持原有的指標正確索引插入的數目。

+0

非常感謝您花時間幫助我思考這個問題! –

相關問題