3

我现在正在处理庞大的数据集。格式是这样的:

1 1 1 1 1 1 1 1 A 1 1 1 1
1 1 1 1 1 1 1 1 A 1 1 1 1
1 1 1 1 1 1 1 1 A 1 1 1 1
1 1 1 1 1 1 1 1 B 1 1 1 1
1 1 1 1 1 1 1 1 B 1 1 1 1
1 1 1 1 1 1 1 1 C 1 1 1 1
1 1 1 1 1 1 1 1 C 1 1 1 1
1 1 1 1 1 1 1 1 C 1 1 1 1

“1”可以不同。我的目标是识别带有“B”的两行(可能有三到四行带有“B”的连续行)并用“B”提取这些行及其周围的行(例如,前两行带有“A”和以下两行带有'C')。这种类型有几个块,我正在考虑使用 for 循环逐行读取文件。每次当我遇到“A”后跟“B”时,都会确定位置。我尝试使用

for line in file:
    if 'A' in line and if 'B' in file.next():

但似乎有些台词丢失了。我的问题是如何使用 for 循环准确识别 AB(或 BC)线对?在那之后,我怎样才能轻松地向后(或向前)几行以在循环中提取所有这些?

4

4 回答 4

2

linecache模块可以通过行号从文件中获取行。您可以在浏览文件时使用它来标记边界点(AB、BC),然后遍历这些行以获得所需的输出。

import linecache

final_lines = []
with open("file.txt") as f:
    for i, line in enumerate(f, 1):
        if "B" in line:
            if "A" in linecache.getline("file.txt", i-1):
                linestart = i - 2  ##2 lines before
            if "C" in linecache.getline("file.txt", i+1):
                lineend = i + 2  ##2 lines after
                for j in range(linestart, lineend+1):
                    final_lines.append(linecache.getline("file.txt", j))
print(final_lines)
于 2013-04-02T03:15:14.780 回答
0

有几种可能的方法可以做到这一点,每种方法都有其优点和缺点。做到这一点的一种方法是保持你已经走过的线路的运行存储,但前提是它们满足特定的标准。例如,假设您阅读了其中包含“A”的行。您开始将这些行存储在一个数组中,直到您点击另一个字母或如果您点击“B”则点击“B”,然后您可以永久存储或输出或您想要对这些数据执行的任何操作。如果您击中不同的字母,则可以擦除缓存。可能的实现可能如下所示。

# Create our temporary storage and final output
cache = []
output_data = []

for line in file:
    # If we find an A lets keep that line in case we find a B after
    if 'A' in line:
        cache.append(line)
    # If we find a B then we take what's in the cache and put it in our final output
    elsif 'B' in line:
        output_data.extend(cache)
        output_data.append(line)  # Add the B line
        cache = [] # We no longer need what was stored here and dont want to store it multiple times if there are more 'B's next.
    else:
        cache = []

这没有考虑到 BC 场景,但正如您所见,这是一种可能的解决方案。这样做的缺点是内存使用。如果您的文件中充满了“A”而最后没有“B”,那么您将在等待找到 B 时将整个文件存储在内存中。

我可能会采取的解决方案是将行号而不是行本身存储在临时内存中。然后在最后再次迭代最终输出我感兴趣的所有行。优点是内存使用较少,但缺点是速度(读取文件两次)。

于 2013-04-02T02:56:10.937 回答
0

这个想法并不是真正在文件中前进和后退,而是跟踪您在流程中的逻辑位置以及所涉及的数据。

这是我们将使用的算法:

  • 保留行的“缓冲区”。首先,我们处于“寻找 A”状态。

  • 在“查找 A”状态下,如果我们找到“A”行,我们将其附加到缓冲区,如果已经有 2 行,我们也会删除缓冲区中的第一行(即我们保留最多 2 行) . 如果我们找到“B”行,则进入“追加所有 B”状态,并处理该行。否则,我们发现了一些其他垃圾,我们清空了缓冲区(因为我们没有找到我们要找的东西)。

  • 在“追加所有 B”状态下,我们不断将“B”行附加到缓冲区,直到找到“C”行或其他任何内容。

等等。这方面的细节取决于您希望如何进行所有错误处理......例如,之前是否必须至少有两个“A”行,之后必须至少有两个“C”行?如果该行不包含任何这些内容怎么办?等等等等。

但基本方法很简单:使用变量来记住“状态”(可以说最简单的方法是使用字符串),然后在for每一行中,您使用if逻辑为每个状态做适当的事情——无论是建立缓冲区,重置缓冲区,更改状态等。

最后,缓冲区应该有你需要的行。

于 2013-04-02T03:13:10.537 回答
0

如果您有非常大的文件要进行提取,我不建议使用 python,实际上您可以使用 awk 或 grep 命令在 linux 上完成所有这些操作。

于 2013-04-02T03:58:56.617 回答