2017-02-22 95 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

非常感谢您花时间帮助我思考这个问题! –

相关问题