我有元组和元组的元组。我很想知道第一个元组的哪些元素与第二元组匹配(如果有的话),考虑到部分匹配。
这是一个过滤功能,用于演示我的意思。
def f(repo):
pattern = (None, None, '1.3')
for idx, item in enumerate(pattern):
if item != None and item != repo[idx]:
return False
return True
>>> repo = (('framework', 'django', '1.3'), ('cms', 'fein', '1.3'), ('cms', 'django-cms', '2.2'))
>>> filter(f, repo)
(('framework', 'django', '1.3'), ('cms', 'fein', '1.3'))
过滤器在这种形式下是无用的,因为模式不能作为参数在外部提供(我想使用相同的函数来检查不同的输入)。有办法解决这个问题吗?
而且,为了更好地解决原始问题,还有什么可以成为另一种算法?
答案 0 :(得分:7)
为什么不使用内置filter
:
>>> filter(lambda x: x[2] == '1.3', repo)
<<< (('framework', 'django', '1.3'), ('cms', 'fein', '1.3'))
...或list comprehension:
>>> [x for x in repo if x[2] == '1.3']
<<< [('framework', 'django', '1.3'), ('cms', 'fein', '1.3')]
如果你想把它包装成一个函数:
types = {'desc': 0, 'name': 1, 'version': 2}
def repo_filter(type, critera, repo=repo, types=types):
return [x for x in repo if x[types[type]] == critera]
>>> repo_filter('version', '1.3')
<<< [('framework', 'django', '1.3'), ('cms', 'fein', '1.3')]
答案 1 :(得分:4)
您可以使用闭包将模式绑定到函数中:
def matcher(pattern):
def f(repo):
return all(p is None or r == p for r, p in zip(repo, pattern))
return f
>>> repo = (('framework', 'django', '1.3'), ('cms', 'fein', '1.3'), ('cms', 'django-cms', '2.2'))
>>> pattern = (None, None, '1.3')
>>> filter(matcher(pattern), repo)
(('framework', 'django', '1.3'), ('cms', 'fein', '1.3'))
我还提供了一个用于比较元组的不同表达式。
答案 2 :(得分:2)
In [43]: [r for r in repo if all((p is None or q==p) for q,p in zip(r,pattern))]
Out[43]: [('framework', 'django', '1.3'), ('cms', 'fein', '1.3')]
答案 3 :(得分:1)
def my_filter(pattern, repo):
def f
pattern = (None, None, '1.3')
for idx, item in enumerate(pattern):
if item != None and item != repo[idx]:
return False
return True
return filter(f, repo)
my_filter((None, None, '1.3'), repo)
答案 4 :(得分:1)
怎么样:
def f(repo, pattern=None):
if not pattern:
pattern = (None, None, '1.3')
for idx, item in enumerate(pattern):
if item and item != repo[idx]:
return False
return True
repo = (('framework', 'django', '1.3'), ('cms', 'fein', '1.3'), ('cms', 'django-cms', '2.2'))
[x for x in repo if f(x)]
>>>[('framework', 'django', '1.3'), ('cms', 'fein', '1.3')]
[x for x in repo if f(x, ('cms',None, None))]
>>> [('cms', 'fein', '1.3'), ('cms', 'django-cms', '2.2')]
答案 5 :(得分:1)
您可以使用以下表达式:
repo = (('framework', 'django', '1.3'), ('cms', 'fein', '1.3'), ('cms', 'django-cms', '2.2'))
p = (None, None, '1.3')
matches = [i for i in repo if i[0]==p[0] or i[1]==p[1] or i[2]==p[2]]
或使用闭包,例如:
def matcher(pattern):
def pattern_matcher(repo):
for idx, item in enumerate(pattern):
if item is not None and item != repo[idx]:
return False
return True
return pattern_matcher
然后可以像这样调用:
filter(matcher(pattern), repo)