匹配列表列表中的索引 - 字典 - python

时间:2015-04-24 12:22:39

标签: python list dictionary

我有一本包含列表清单的字典:

d = [('Locus_1',
  [['>Safr02', 'R', '104'],
   ['>Safr03', 'G', '104'],
   ['>Safr04', 'A', '104'],
   ['>Safr10', 'A', '104'],
   ['>Safr02', 'K', '110'],
   ['>Safr03', 'T', '110'],
   ['>Safr04', 'T', '110'],
   ['>Safr10', 'T', '110']]),
 ('Locus_2',
  [['>Safr01', 'C', '15'],
   ['>Safr02', 'Y', '15'],
   ['>Safr04', 'Y', '15'],
   ['>Safr07', 'Y', '15'],
   ['>Safr01', 'Y', '78'],
   ['>Safr02', 'T', '78'],
   ['>Safr04', 'T', '78'],
   ['>Safr07', 'T', '78']])]

使用以下代码创建字典:

snp_file = open(sys.argv[2], 'r')
snps = csv.reader(snp_file, delimiter=',')

d = OrderedDict()

for row in snps:
    key = row[0]
    d.setdefault(key,[])
    d[key].append(row[1:])

可在此处找到数据:https://www.dropbox.com/sh/3j4i04s2rg6b63h/AADkWG3OcsutTiSsyTl8L2Vda?dl=0

我有一个(对我来说)这个数据的复杂任务,我想把它分成几个步骤,但我不知道如何做到这一点:

我需要关于Locus_X名称成对地查看数据(我在另一个文件中有一个对列表,但对于这个问题,我们只说Locus_1Locus_2是一个对)。

因此,对于Locus_1:Locus_2对,我需要匹配每个locus-list(SafrXX)中位置0的名称。对于那些相等的(So Locus_1:Safr02-Locus_2:Safr02),我需要比较位置1处的字母 - 所以对于这个例子,字母将是:R:Y

为了使它变得更加棘手,我需要对位置2的值的所有组合执行此操作。

所以我在上面要比较的字母是:

R:Y
R:T
K:Y
K:T

现在,我并不是要求您编写一段代码,实际上可以执行此操作,但是,分离和处理此任务的最合理的方法是什么?有没有我可以先做的事情,所以我不必在复杂的多个嵌套循环中做所有事情?

2 个答案:

答案 0 :(得分:0)

我认为这里描述的问题并不好。或者更好的是,您提供的数据的依赖关系将解释您需要的输出。

我用你的代码玩了一下,首先我认为通过像这样使用zip function的python会很简单:

import csv
from collections import OrderedDict

snp_file = open('data.txt', 'r')
snps = csv.reader(snp_file, delimiter=',')
d = OrderedDict()
for row in snps:
    key = row[0]
    d.setdefault(key,[])
    d[key].append(row[1:])

for left,right in zip(d['Locus_1'],d['Locus_2']):
    print(left,right)

这给了我以下输出,它不会帮助你,因为第一个列未排序且不匹配:

['>Safr02', 'R', '104'] ['>Safr01', 'C', '15']
['>Safr03', 'G', '104'] ['>Safr02', 'Y', '15']
['>Safr04', 'A', '104'] ['>Safr04', 'Y', '15']
['>Safr10', 'A', '104'] ['>Safr07', 'Y', '15']
['>Safr02', 'K', '110'] ['>Safr01', 'Y', '78']
['>Safr03', 'T', '110'] ['>Safr02', 'Y', '78']
['>Safr04', 'T', '110'] ['>Safr04', 'T', '78']
['>Safr10', 'T', '110'] ['>Safr07', 'T', '78']

为此脚本添加排序再次没有帮助,因为列表的长度相同,但第一个键在数据中不匹配:

loc1 = sorted(d['Locus_1'], key=lambda lst: lst[0]): 
loc2 = sorted(d['Locus_2'], key=lambda lst: lst[0]): 

for left,right in zip(loc1,loc2):
    print(left,right)

将以下内容放入屏幕:

['>Safr02', 'R', '104'] ['>Safr01', 'C', '15']
['>Safr02', 'K', '110'] ['>Safr01', 'Y', '78']
['>Safr03', 'G', '104'] ['>Safr02', 'Y', '15']
['>Safr03', 'T', '110'] ['>Safr02', 'Y', '78']
['>Safr04', 'A', '104'] ['>Safr04', 'Y', '15']
['>Safr04', 'T', '110'] ['>Safr04', 'T', '78']
['>Safr10', 'A', '104'] ['>Safr07', 'Y', '15']
['>Safr10', 'T', '110'] ['>Safr07', 'T', '78']

所以我切换到嵌套循环,看看我是否能更好地掌握数据的处理方式:

for l1 in loc1:
    for l2 in loc2:
        if l1[0] == l2[0]:
            print('{}-{}({}):{}({})'.format(l1[0],l1[1],l1[2],l2[1],l2[2]))

但是,这并没有给我一个线索,但看到自己(输出是短暂的,因为我仍然没有掌握要点):

>Safr02-R(104):Y(15)
>Safr02-R(104):Y(78)
>Safr02-K(110):Y(15)
>Safr02-K(110):Y(78)
>Safr04-A(104):Y(15)
>Safr04-A(104):T(78)
>Safr04-T(110):Y(15)
>Safr04-T(110):T(78)

所以你看,如果你在一个嵌套循环中完成它,你将很容易实现你的目标 - 至少靠近它一步。但是,您似乎正在寻找正确处理数据所需的逻辑,而不会告诉我们数据背后的逻辑。

使用代码你已经可以匹配列表并将field1中的字母与field2的所有组合进行比较,但是field3的数量应该如何影响你的输出我不清楚。

无论如何,我希望这至少有一点帮助。

答案 1 :(得分:0)

这是我的解决方案。将pair变量替换为要检查的任何配对位点对。我将行的索引添加到元组中,因为排序很重要。

import csv

snp_file = open('input.txt', 'r')
snps = csv.reader(snp_file, delimiter=',')
pair=(1,2)#the choosen pair

dic={}
i=0
for row in snps:
    if row==[]: break
    locus=int(row[0][len('locus_'):])
    safr=int(row[1][len('>safr'):])
    letter=row[2]
    number=row[3]
    index=i
    if (locus, safr) in dic:
        dic[locus, safr].append((letter, number, index))
    else:
        dic[locus, safr]=[(letter, number, index)]
    i+=1

for key in dic:
    if key[0]==pair[0] and (pair[1], key[1]) in dic:
        for e in dic[key]:
            for f in dic[pair[1], key[1]]:
                print e, ' ', f

这给出了以下输出:

('R', '104', 0)   ('Y', '15', 9)
('R', '104', 0)   ('T', '78', 13)
('K', '110', 4)   ('Y', '15', 9)
('K', '110', 4)   ('T', '78', 13)
('A', '104', 2)   ('Y', '15', 10)
('A', '104', 2)   ('T', '78', 14)
('T', '110', 6)   ('Y', '15', 10)
('T', '110', 6)   ('T', '78', 14)