【问题标题】:While loop works for small to medium sized data but not larger amounts of data. (Python)While 循环适用于中小型数据,但不适用于大量数据。 (Python)
【发布时间】:2017-07-13 19:19:39
【问题描述】:

好的,对于一个问题,我必须解析两个信息文件,然后比较这些文件。我需要报告任何不一致的数据以及一个文件中而不是另一个文件中的任何数据。为此,我对两个数据列表进行了排序,这允许我比较每个列表中的第一个元素,如果它们相等,我将它们删除,如果它们不一致,我报告并删除它们,如果一个或另一个不同,我报告哪个缺少数据,然后将其放回较晚的日期,以便下次进行比较。

正如您在我的代码中看到的(至少我认为并且已经过广泛测试),这种方法适用于每个文件包含 100-200 行的数据集。当我变得更大时,比如 1,000-1,000,000,报告需要很长时间。

我对我的 while 循环如何导致这种情况感到困惑。见下文。 分割代表日期(split[0]),然后是一条信息(split[1])。

任何帮助将不胜感激,这实际上是我的第一个 python 程序。

tldr;出于某种原因,我的程序在小型数据集中运行良好,但较大的数据集无法正常运行。它也不是 sort() 的(即我的第一个 while 循环中的某些东西导致运行时间很糟糕)。

ws1.sort()
ws2.sort()

while ws1 and ws2:
    currItem1 = ws1.pop(0)
    currItem2 = ws2.pop(0)
    if currItem1 == currItem2:
        continue
    splitWS1 = currItem1.split()
    splitWS2 = currItem2.split()
    if splitWS1[0] == splitWS2[0] and splitWS1[1] != splitWS2[1]:
        print("Inconsistent Data (" + splitWS1[0] + "): A: " + splitWS1[1] + " B: " + splitWS2[1])
        continue
    elif splitWS1[0] < splitWS2[0]:
        print("Missing Data (" + splitWS1[0] + ") in data set A but not in B")
        ws2.insert(0, currItem2)
        continue
    elif splitWS1[0] > splitWS2[0]:
        print("Missing Data (" + splitWS2[0] + ") in data set B but not in A")
        ws1.insert(0, currItem1)
        continue
while ws2:
    currItem2 = ws2.pop(0)
    splitWS2 = currItem2.split()
    print("Missing data (" + splitWS2[0] + ") in data set B but not in A")
while ws1:
    currItem1 = ws1.pop(0)
    splitWS1 = currItem1.split()
    print("Missing data (" + splitWS1[0] + ") in data set A but not in B")

【问题讨论】:

  • while ws1 and ws2: --> while ws1 or ws2:
  • 是否需要很长时间,或者是否存在较大的数据集导致错误结果的实际问题?
  • @SpencerWieczorek 我认为他说的问题是需要一段时间,输出没有实际问题,至少如果我正在阅读他正确写的内容。
  • 也许可以考虑使用包含 for 循环的生成器函数,使用 yield 而不是 return。生成器会根据您的需要逐步返回 ws1 和 ws2 的值,而不是一次全部返回。
  • 仔细观察会发现,对于非常大的数据集来说,三个循环可能太多了,而且只需要很长时间才能遍历所有数据。

标签: python


【解决方案1】:

很可能是这两行:

currItem1 = ws1.pop(0)
currItem2 = ws2.pop(0)

当您删除列表中的第一项时,您必须重建整个列表。如果您尝试使用(循环外):

listA = list(reversed(ws1.sorted()))

然后在循环中处理

currItem1 = listA.pop()

对于这两个列表中的每一个,您都可以节省很多处理时间。

基本上,删除列表中的第一项是 O(n),而删除列表中的最后一项是 O(1)。在循环中这样做意味着它是 O(n^2),但是如果你事先将列表反转一次,然后删除列表中的最后一项,它就是 O(n)。

【讨论】:

  • 您可以使用reverse() 方法反转列表。由于当前代码已经破坏了输入列表,我认为没有任何理由用list(reversed(...)) 复制它们。
  • 所以这实际上帮助了很多。我有一种感觉,它可能是这样的。我所要做的就是排序然后反转两个列表并使用 pop() 并大大减少了时间。当然,我发现上述代码仍然存在问题,但这确实解决了我的时间复杂度问题。谢谢@Darthfett
  • @neuro9 很高兴为您提供帮助。 :) 了解内置数据结构上的各种操作的Time Complexity 总是一个好主意。如果您还不了解Big O notation,您还应该阅读它。
猜你喜欢
  • 1970-01-01
  • 2016-01-31
  • 1970-01-01
  • 1970-01-01
  • 2021-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多