【问题标题】:finding gappy sublists within a certain range在一定范围内找到有间隙的子列表
【发布时间】:2018-05-21 08:00:36
【问题描述】:

最近I asked a question here 我想在更大的列表中找到子列表。我有一个类似但略有不同的问题。假设我有这个列表:

 [['she', 'is', 'a', 'student'],
 ['she', 'is', 'a', 'lawer'],
 ['she', 'is', 'a', 'great', 'student'],
 ['i', 'am', 'a', 'teacher'],
 ['she', 'is', 'a', 'very', 'very', 'exceptionally', 'good', 'student']] 

我想使用matches = ['she', 'is', 'student'] 查询它,目的是从查询列表中以相同的顺序获取包含matches 元素的所有子列表。与链接中问题的唯一区别是我想向 find_gappy 函数添加一个 range 参数,这样它就不会检索元素之间的间隙超过指定范围的子列表。例如,在上面的例子中,我想要一个这样的函数:

matches = ['she', 'is', 'student']
x = [i for i in x if find_gappy(i, matches, range=2)]

会返回:

[['she', 'is', 'a', 'student'], ['she', 'is', 'a', 'great', 'student']]

最后一个元素没有出现,因为在句子she is a very very exceptionally good student中,agood之间的距离超过了范围限制。

这样的函数怎么写?之间的差距

【问题讨论】:

  • 是否应该在任何单词之间应用 gappy 限制,或者它是一个集体 gappy 限制 - 即是否应该 ['she', 'xxx', 'yyy', 'is', 'a', 'zzz', 'student'] 匹配,因为最大任意两个词之间的gap是2,但总gap是4。
  • 要么扩大范围限制,要么完全删除它——看起来很明显,所以我认为你不能这样做是有原因的?顺便说一句,我和克莱姆的侄女一起上大学!
  • @zwer 间隙限制适用于任何单词之间。这不是一个集体限制。
  • matches的顺序呢?它总是与传递给函数的原始匹配相同吗?
  • @PaulaThomas 我侄女不记得你了,你在骂人。 :-D

标签: python python-3.x list pattern-matching sublist


【解决方案1】:

这是一种考虑match 列表中项目顺序的方法:

In [102]: def find_gappy(all_sets, matches, gap_range=2):
     ...:     zip_m = list(zip(matches, matches[1:]))
     ...:     for lst in all_sets:
     ...:         indices = {j: i for i, j in enumerate(lst)}
     ...:         try:
     ...:             if all(0 <= indices[j]-indices[i] - 1 <= gap_range for i, j in zip_m):
     ...:                 yield lst
     ...:         except KeyError:
     ...:             pass
     ...:         
     ...:   

演示:

In [110]: lst = [['she', 'is', 'a', 'student'],
     ...:  ['student', 'she', 'is', 'a', 'lawer'],  # for order check
     ...:  ['she', 'is', 'a', 'great', 'student'],
     ...:  ['i', 'am', 'a', 'teacher'],
     ...:  ['she', 'is', 'a', 'very', 'very', 'exceptionally', 'good', 'student']] 
     ...:  

In [111]: 

In [111]: list(find_gappy(lst, ['she', 'is', 'student'], gap_range=2))
Out[111]: [['she', 'is', 'a', 'student'], ['she', 'is', 'a', 'great', 'student']]

如果您的子列表中有重复的单词,您可以使用defaultdict() 跟踪所有索引,并使用itertools.prodcut 比较单词对的所有有序产品的差距。

In [9]: from collections import defaultdict
In [10]: from itertools import product

In [10]: def find_gappy(all_sets, matches, gap_range=2):
    ...:     zip_m = list(zip(matches, matches[1:]))
    ...:     for lst in all_sets:
    ...:         indices = defaultdict(list)
    ...:         for i, j in enumerate(lst):
    ...:             indices[j].append(i)
    ...:         try:
    ...:             if all(any(0 <= v - k - 1 <= gap_range for k, v in product(indices[j], indices[i])) for i, j in zip_m):
    ...:                 yield lst
    ...:         except KeyError:
    ...:             pass

【讨论】:

    【解决方案2】:

    链接问题中的技术足够好,您只需要沿途添加间隙计数,并且由于您不想要全局计数,因此每当遇到匹配时重置计数器。比如:

    import collections
    
    def find_gappy(source, matches, max_gap=-1):
        matches = collections.deque(matches)
        counter = max_gap  # initialize as -1 if you want to begin counting AFTER the first match
        for word in source:
            if word == matches[0]:
                counter = max_gap  # or remove this for global gap counting
                matches.popleft()
                if not matches:
                    return True
            else:
                counter -= 1
                if counter == -1:
                    return False
        return False
    
    data = [['she', 'is', 'a', 'student'],
            ['she', 'is', 'a', 'lawer'],
            ['she', 'is', 'a', 'great', 'student'],
            ['i', 'am', 'a', 'teacher'],
            ['she', 'is', 'a', 'very', 'very', 'exceptionally', 'good', 'student']]
    
    matches = ['she', 'is', 'student']
    x = [i for i in data if find_gappy(i, matches, 2)]
    # [['she', 'is', 'a', 'student'], ['she', 'is', 'a', 'great', 'student']]
    

    作为奖励,您可以将其用作原始函数,仅当您将正数作为max_gap 传递时才会应用间隙计数。

    【讨论】:

      猜你喜欢
      • 2016-03-07
      • 2023-03-10
      • 2018-07-03
      • 2011-09-21
      • 2022-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多