簡體   English   中英

有沒有辦法在字典列表中的下一個字典中獲取相同鍵的下一個值?

[英]Is there a way to get next value for the same key in the next dictionary in the list of dictionaries?

我有兩個不同的字典列表, list_alist_b 第一個詞典列表包含核苷酸位點,而其他詞典列表則包含所有基因的開始和結束坐標。 如果該位點落入基因坐標的范圍內,則該位點屬於該基因。 但是有時候,即使一個位點在該范圍之外,它仍然屬於該基因。 例如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()函數,但無法正常工作。

更為有效的方法是將每個 Ch值的各個部分按排序順序解析為一個結構:

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_a Ch值的范圍內:

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

range可迭代的“記住”第next()搜索停止的地方,我們可以在其上循環以繼續從該點開始搜索合適的stop值。

請注意,大概stop值將始終等於或大於start值。 是在對於下一個項目的測試沒有點start值,以及; 如果site <= stopTruesite <= start 也是 True

我認為您也許可以做一些更簡單的事情。

在list_b中,您可以添加一個名為site:的新密鑰,您可以將其設置為(start + end)/ 2。

然后合並list_a和list_b,並按sorted_list中的鍵(Ch :, site :)對其進行排序。

然后一次通過sorted_list。 如果它是一個基因(來自list_a),請跳過它並跟蹤其名稱:如果它是一個站點(來自list_b),則將其名稱設置為上一項的名稱:或使用名稱:您保存的。

可能需要對“最接近的內容”進行一些調整,但是我確信您可以通過向前和向后查看當前職位並執行一些適當的業務邏輯來做到這一點。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM