【问题标题】:List comprehension with a Boolean whose value changes throughout iterations带有布尔值的列表理解,其值在整个迭代过程中都会发生变化
【发布时间】:2020-12-23 13:30:31
【问题描述】:

我正在尝试从带有 if 语句的嵌套 for 循环创建列表推导,但我无法弄清楚。我在互联网上扫描了几个小时,但找不到解决方案。

循环看起来像这样:

lengths = []
data_frame = p.read_excel(fasta_path_[:-2] + 'xlsx', engine='openpyxl')
seqids = data_frame['qseqid'].tolist()
identical_ids = None

with open(fasta_path_, 'r') as fasta_file:
    for line in fasta_file.readlines():
        if identical_ids is True:
            lengths.append(len(line.strip()))
        for seq_id in seqids:
            if seq_id in line:
                identical_ids = True
                continue
            else:
                identical_ids = False
                continue

我的最后一次尝试:

lengths = [len(line.strip()) for line in fasta_file.readlines() if identical_ids for seq_id in seqids if seq_id in line identical_ids := True else identical_ids := False]

编辑

多次运行和修复代码后,看起来最终结果无法写成列表推导:

seqids = p.read_csv(csv_path, usecols=['qseqid'])
seqids = seqids['qseqid'].tolist()
queries_lengths = []
count = 0
id_in_tag_line = None
with open(fasta_path_, 'r') as fasta_file:
    for line in fasta_file.readlines():
        if count < len(seqids) and seqids[count] in line:
            id_in_tag_line = True
            count += 1
            continue
        if id_in_tag_line:
            queries_lengths.append(len(line))
            id_in_tag_line = None

由于这段代码中使用的两个列表非常大,for 循环运行了大约 30,000 个,所以我没有使用嵌套的 for 循环,而是使用了一个计数器。

如果有人认为有办法(或需要)将其编写为列表理解,我很乐意听到新的想法。

【问题讨论】:

  • 列表理解是关于创建一个包含一些值的列表;您的第二个循环与在列表中包含值无关。
  • 你为什么要这样做?该列表理解使代码更易于阅读还是更难阅读?
  • 也许你可以使用walrus 操作符来做到这一点,但对我来说,第一个解决方案更具可读性。

标签: python if-statement list-comprehension nested-loops


【解决方案1】:

这里有一个更简化的代码版本,它做同样的事情:

identical_ids = None

with open(fasta_path_, 'r') as fasta_file:
    for line in fasta_file:
        if identical_ids:
            lengths.append(len(line.strip()))
        identical_ids = seqids[-1] in line

应该更容易使用。

这里是列表理解:

with open(fasta_path_, 'r') as fasta_file:
    lengths = [len(line.strip()) for i, line in enumerate(fasta_file) if seqids[-1] in line and i]

sedis[-1]的解释:

你有

        for seq_id in seqids:
            if seq_id in line:
                identical_ids = True
                continue
            else:
                identical_ids = False
                continue

您基本上是在遍历seqids 数组,并将identical_ids 设置为每个元素是否在line 中。

一直迭代到seqids的最后一个元素,identical_ids会被设置为最后一个元素是否在line中,使得之前的迭代为null。

【讨论】:

    【解决方案2】:

    这段代码正在做什么或试图做什么的解释归结为这个子句:

    for seq_id in seqids:
        if seq_id in line:
            identical_ids = True
            continue
        else:
            identical_ids = False
            continue
    

    正如@AnnZen 在她的回答中指出的那样,这是有效的:

    identical_ids = seqids[-1] in line
    

    但这使得代码在其方法以及使用两个continue no-ops 时存在问题。假设代码略有损坏,它可能打算阅读:

    for seq_id in seqids:
        if seq_id in line:
            identical_ids = True
            break
        else:
            identical_ids = False
            continue
    

    也就是说,seqidany 元素在 line 中找到。或者它可能打算阅读:

    for seq_id in seqids:
        if seq_id in line:
            identical_ids = True
            continue
        else:
            identical_ids = False
            break
    

    seqids所有元素都包含在line中。两种解释仍然包括一个continue no-op。无论如何,在 OP 阐明预期功能之前,将其简化为列表理解似乎是不合理的。

    【讨论】:

    • 酷,2500 个答案!
    • “在 OP 阐明预期的功能之前,将其简化为列表理解似乎是不合理的” 由 th OP 声明:“我正在尝试创建一个列表理解”
    • @AnnZen,list comprehensionform,而不是 function。而且我不知道您的其他评论是什么意思。
    • 你是什么意思“不是函数”? OP 的尝试怎么样:lengths = [len(line.strip()) for line in fasta_file.readlines() if identical_ids for seq_id in seqids if seq_id in line identical_ids := True else identical_ids := False] 另一个评论的意思是this
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-08
    • 2013-05-11
    • 1970-01-01
    • 2021-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-12
    相关资源
    最近更新 更多