我正在尝试使用递归比较两个列表之间的元素值。对于索引i
,if list1[i] = A and list2[i] = T
,反之亦然,这些值有效。同样,对于索引i,if list1[i] = G and list2[i] = C
,反之亦然,这些值均有效。但是,如果不满足这两个条件(list1[i] = A and list2[i] = G
),则该值无效。我创建了两个新列表,其中存储了有效值,并将无效值替换为空白''。
此代码可与for循环(for i in range (0, len(list1)):
)配合使用,但是如何使用递归?
def check_valid(sequence1, sequence2):
sequence1 = list(sequence1)
sequence2 = list(sequence2)
valid_units1 = []
valid_units2 = []
if (sequence1[i] == 'A' and sequence2[i] == 'T') or (sequence1[i] == 'T' and sequence2[i] == 'A'):
valid_units1.append(sequence1[i])
valid_units2.append(sequence2[i])
elif (sequence1[i] == 'G' and sequence2[i] == 'C') or (sequence1[i] == 'C' and sequence2[i] == 'G'):
valid_units1.append(sequence1[i])
valid_units2.append(sequence2[i])
else:
valid_units1.append(' ')
valid_units2.append(' ')
print(valid_units1)
print(valid_units2)
valid_units = [valid_units1, valid_units2]
return valid_units
答案 0 :(得分:1)
如果您从两个列表开始,并且想要逐个比较它们,则可以使用zip()
来简化生活。它将使您恢复配对的元素。因此,如果您从两个列表开始,则可以zip
:
list1 = ['A', 'T']
list2 = ['C', 'G']
zipped = list(zip(list1, list2))
# zipped is [('A', 'C'), ('T', 'G')]
#or use a list comprehension:
zipped = [pair for pair in zip(list1, list2)]
zip()
返回一个迭代器,这就是将其包装在上面的list()
中的原因。如果您在循环中或其他需要使用插入器的情况下使用它,则无需这样做。
如果要比较这些字母,可以使用一个字典,该字典定义哪个字母映射到另一个字母,这将使您编写一个更简单的测试函数:
# Define a mapping that describes which elements belong togethre
pairs = {
'G':'T',
'T':'G',
'C':'A',
'A':'C'
}
list1 = ['A', 'A', 'T', 'C', 'G', 'C', 'T', 'A']
list2 = ['C', 'G', 'G', 'A', 'C', 'A', 'C', 'T']
# make a new list if the pairs line up with the mapping:
legal = [(a, b) for a, b in zip(list1, list2) if pairs[a] == b ]
# legal pairs: [('A', 'C'), ('T', 'G'), ('C', 'A'), ('C', 'A')]
没有太多理由递归执行此操作,但是您当然可以。由于zip()
返回一个迭代器(下面的pairs
),因此您可以在其上调用next()
到达下一个值,然后将迭代器传递回去。缺项时将引发StopIteration
错误,因此可能是递归的边缘条件:
def buildList(pairs, mapping):
''' Takes an iterator and mapping, returns a list of legal items defined by mapping '''
try:
a_pair = next(pairs) # get first item from zipped list
except StopIteration: # no more items, just return an empty list
return []
a, b = a_pair
if mapping[a] == b:
return [(a, b)] + buildList(pairs, mapping)
else:
return buildList(pairs, mapping)
list1 = ['A', 'A', 'T', 'C', 'G', 'C', 'T', 'A']
list2 = ['C', 'G', 'G', 'A', 'C', 'A', 'C', 'T']
pairs = {'G':'T','T':'G','C':'A','A':'C'}
buildList(zip(list1, list2), pairs) # use zip to make the zipped iterator
答案 1 :(得分:0)
此问题带有递归标签,这是我的看法-
subcription
这很直观,但是与def head(xs = []):
return xs[0]
def tail(xs = []):
return xs[1:]
def check_pair(x = "", y = "", swap = True):
if x == "A" and y == "C":
return True
elif x == "G" and y == "T":
return True
else:
return swap and check_pair(y, x, False)
def check_valid(a = [], b = []):
if (not a) or (not b):
return
elif check_pair(head(a), head(b)):
yield (head(a), head(b))
yield from check_valid(tail(a), tail(b))
else:
yield from check_valid(tail(a), tail(b))
a = ['A', 'A', 'T', 'C', 'G', 'C', 'T', 'A']
b = ['C', 'G', 'G', 'A', 'C', 'A', 'C', 'T']
print(list(check_valid(a,b)))
# [('A', 'C'), ('T', 'G'), ('C', 'A'), ('C', 'A')]
类似,zip
函数创建中间值。我们可以使用简单的索引tail
-
i
您可能对此related Q&A
感兴趣