【问题标题】:Read specific sequence of lines in Python在 Python 中读取特定的行序列
【发布时间】:2016-03-07 00:27:14
【问题描述】:

我有一个如下所示的示例文件:

    @XXXXXXXXX
    VXVXVXVXVX
    +
    ZZZZZZZZZZZ
    @AAAAAA
    YBYBYBYBYBYBYB
    ZZZZZZZZZZZZ
    ...

我希望只阅读索引 4i+2 上的行,其中 i 从 0 开始。所以我应该阅读上面 sn-p 中的 VXVXV (4*0+2 = 2)... 行和 YBYB...(4*1 +2 = 6) 行。我需要计算'V's, 'X's,'Y's and 'B's 的数量并存储在预先存在的字典中。

fp = open(fileName, "r")
lines = fp.readlines()

for i in xrange(1, len(lines),4):
    for c in str(lines(i)):
        if c == 'V':
             some_dict['V'] +=1

谁能解释我如何避免退出索引而只读取行列表的 4*i+2 索引处的行?

【问题讨论】:

  • 很遗憾,这不正确。

标签: python list file indexing readlines


【解决方案1】:

你不能只对行列表进行切片吗?

lines = fp.readlines()
interesting_lines = lines[2::4]

为其他质疑其工作原理的人编辑:

“完整”切片语法由三部分组成:start:end:step

start 是起始索引,默认为 0。因此,对于 4 * i + 2,当 i == 0 时,即索引 #2。

end 是结束索引,默认情况下是 len(sequence)。切片上升到 但不包括最后一个索引。

step 是所选项目之间的增量,默认为 1。通常,像3:7 这样的切片将返回元素 3、4、5、6(和 not 7)。但是当你添加一个step 参数时,你可以执行“step by 4”之类的操作。

只要正确选择了start 参数,执行“按4 步”表示start+0, start+4, start+8, start+12, ... 这是OP 想要的。

【讨论】:

  • 在这种情况下是lines[1::4],但是是的,这可以在不使用索引的情况下获取所需的行。
  • 嘿,这比我的双重列表组合更明智。 +1
  • 就像一个魅力! @Ittociwam 你能解释一下这种切片是如何转化为逻辑的吗?
  • 我对这个切片如何看待每个 4*i+2 索引感到困惑。 @Ittociwam
  • 对不起,我的意思是说它避免了 for 循环的“脱离索引”。假设这就是 op 的意思。
【解决方案2】:

您可以执行以下操作之一:

从 0 开始 xrange 然后在二级循环中将 2 添加到 i

for i in xrange(0, len(lines), 4):
    for c in str(lines(i+2))
        if c == 'V':
            some_dict['V'] += 1

从2开始xrange,然后按照你原程序中指定的方式访问i

for i in xrange(2, len(lines), 4):
    for c in str(lines(i))
        if c == 'V':
            some_dict['V'] += 1

【讨论】:

    【解决方案3】:

    我不太清楚你在这里要做什么——你实际上只是想从磁盘上只读取你想要的行吗? (在这种情况下,您从一开始就出错了,因为readlines() 读取了整个文件。)或者您只是想过滤行列表以挑选出您想要的行?

    我假设是后者。在这种情况下,最简单的方法就是使用 listcomp 按索引过滤行。例如像这样简单的东西:

    indices = [x[0] * 4 + 2 for x in enumerate(lines)]
    filtered_lines = [lines[i] for i in indices if len(lines) > i]
    

    然后你就得到了你想要的行,没有索引错误或任何类似的愚蠢。然后,您可以分离并简化其余代码以进行计数,只需对过滤后的列表进行操作即可。

    (只是稍微编辑了第一个列表组合,使其更加惯用)

    【讨论】:

    • 从技术上讲,我只需要阅读 4*i+2 处的行,但为了简单起见,我只是避免进行该优化。我会试试这个listcomp。谢谢!
    • 请注意一些修改 --- 第一个 listcomp 现在更惯用了,第二个删除了一个错误。
    【解决方案4】:

    我已经对另一个问题给出了类似的答案:How would I do this in a file?

    更好的解决方案(避免不必要的 for 循环)是

    fp = open(fileName, "r")
    def addToDict(letter):
        someDict[letter] += 1;
    
    [addToDict('V') for 'V' in str(a) for a in fp.readlines()[2::4]];
    

    我试图使它成为一个匿名函数,但没有成功,如果有人能做到,那就太好了。

    【讨论】:

    • 你能解释一下吗:[2::4]?
    • 当您对结果列表不感兴趣时​​,为什么要使用列表推导?此外,该功能是完全没有必要的。 [somedict['V']+=1 ... ] 更像是pythonic。这并不能避免任何 for 循环,您只是看不到列表理解后面的 for 循环。此外,似乎 OP 每次匹配时都试图增加 'V' 的计数,而不是每行一次
    • Python 将从索引 2 开始读取列表,然后每隔四个元素读取一次。它被称为切片。以下示例适用于 Numpy 数组,但也适用于常规列表:structure.usc.edu/numarray/node26.html
    • asdf:您建议的语法在 Python 2.7 中为我抛出了一个错误(IDK,如果这在 Python 3 中已更改)。是的,for 循环是隐藏的;我的建议中没有 explicit for 循环;列表理解方法更快。编辑:你说得对,我没有正确阅读原始代码,OP 每次读取“V”时都想加 1。更新我的答案。
    • @Wer900 在 for 循环实际构建列表 (See here) 的情况下,列表推导更快。但是,在这种情况下,没有构建列表,我们只是附加到字典中。累积无用值会显着减慢运行时间。在这种情况下,列表解析实际上比等效的 for 循环
    猜你喜欢
    • 1970-01-01
    • 2019-05-12
    • 1970-01-01
    • 2021-10-28
    • 2013-06-03
    • 2013-12-02
    • 2016-12-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多