有没有办法为字典列表中的下一个字典中的同一个键获取下一个值?

2024-04-25 06:46:17 发布

您现在位置:Python中文网/ 问答频道 /正文

我有两个不同的词典列表,list_alist_b。第一个字典列表包含核苷酸位点,另一个字典列表包含所有基因的起始和结束坐标。如果该位点在基因坐标范围内,则该位点属于该基因。然而,有时即使一个位点在这个范围之外,它仍然属于这个基因。E、 g来自list_a的站点,第二个字典-8属于gene_b。你知道吗

list_a = [{'Ch': 'I', 'name': 'test_1', 'site': 2}, {'Ch': 'II', 'name': 'test_2', 'site': 8}, {'Ch': 'II', 'name': 'test_3', 'site': 10}]

list_b = [{'Ch': 'I', 'name': 'gene_a', 'start': 1, 'end': 3}, {'Ch': 'II', 'name': 'gene_b', 'start': 3, 'end': 6}]   

这是第一部分,工作良好。你知道吗

for item_a in list_a:
    for item_b in list_b:
        if item_a['Ch'] == item_b['Ch'] and item_a['site'] >= item_b['start'] and item_a['site'] <= item_b['end']:
            print item_b['name'], item_a['site']

所以我想要这样的东西

if item_a['site'] >= item_b['start'] and item_a['site'] >= item_b['end']
and item_a['site'] <= the next site in the next dictionary in list_a... 
or the beginning of the next gene in the next dictionary... ???

(我已经学会了如何按键排列字典列表)

我试着使用next()函数,但没能让它工作。你知道吗


Tags: thenamein列表字典基因sitech
2条回答

更有效的方法是按排序顺序将节解析为结构perCh值:

from collections import defaultdict
import bisect

ranges = defaultdict(list)
for info in list_b:
    bisect.insort(ranges[info['Ch']], (info['start'], info['end'], info['name']))

bisect.insort()调用按排序顺序将新条目插入列表,从而为您节省另一个排序循环。你知道吗

现在用这个来定位给定list_aCh值的范围:

for gene in list_a:
    for start, stop, name in ranges[gene['Ch']]:
        if start <= gene['site'] <= stop:
            print name, gene['site']
            break

当然,这仍然不会根据“stop”参数搜索下一个匹配项,但是后一个循环可以被折叠成一个生成器表达式,适合在next()函数中使用,并且由于范围已排序,因此可以继续搜索下一个站点名称:

for gene in list_a:
    site = gene['site']
    range = iter(ranges[gene['Ch']])
    # skip anything with start > site
    name = previous = next((name for start, stop, name in range if start <= site), None)

    # search on for a matching stop, looking ahead. If we find a stop < site
    # the previous entry matched. If we ran of the end of our options, the last
    # entry matched.
    for start, stop, name  in range:
        if site > stop:
            previous = name
            continue
        if start > site:
            name = previous
        break

    print name, site

rangeiterable“记住”第一次next()搜索停止的位置,我们可以循环遍历它,从该点开始继续搜索合适的stop值。你知道吗

注意,假设stop值是总是将等于或大于start值;测试下一个项目start值也没有意义;如果site <= stopTrue,那么site <= start也是也是^{True。你知道吗

我想你可以做些更直截了当的事。你知道吗

在列表b中,您可以添加一个名为site:的新键,您可以将其设置为(start+end)/2。你知道吗

然后合并列表a和列表b,并按排序后的列表中的键(Ch:,site:)对它们进行排序。你知道吗

然后一次列出一个。如果它是一个基因(来自列表a),请跳过它并跟踪它的名称:如果它是一个站点(来自列表b),请将它的名称设置为上一个项目的名称:或使用您保存的名称。你知道吗

可能有一些“什么是最接近的”做调整,但我相信你可以做的前瞻性和背后,你目前的立场,做一些适当的业务逻辑。你知道吗

相关问题 更多 >