假设我们有一个字符串1 A B C D E F
和一个字符串2 B D E
(这些字母仅用于演示,实际上它们是单词)。现在我想知道是否有任何n
一致的"单词"来自字符串1中的字符串2.要将字符串转换为"字词",我使用string.split()
。
例如n
等于2,我想检查B D
或D E
是否 - 按此顺序 - 在字符串1中{{ 1}}在字符串中不按此顺序排列,但B D
是。
有没有人看到这样做的pythonic方式?
我确实有D E
等于2的解决方案,但意识到我需要任意n。它也不是特别漂亮:
n
答案 0 :(得分:2)
使用正则表达式很容易:
>>> import re
>>> st1='A B C D E F'
>>> st2='B D E'
>>> n=2
>>> pat=r'(?=({}))'.format(r's+'.join(r'\w+' for i in range(n)))
>>> print [(s, s in st1) for s in re.findall(pat, st2)]
[('B D', False), ('D E', True)]
关键是使用零宽度向前看以找到字符串中的重叠匹配。所以:
>>> re.findall('(?=(\\w+\\s+\\w+))', 'B D E')
['B D', 'D E']
现在构建n
重复\w+
找到的单词:
>>> n=2
>>> r'(?=({}))'.format(r's\+'.join(r'\w+' for i in range(n)))
'(?=(\\w+\\s+\\w+))'
现在因为你有两个字符串,所以使用Python的in
运算符从正则表达式匹配到目标字符串产生s
结果的元组。
当然如果你想要一个非正则表达式来做这个,只需用n生成n个字的子串:
>>> li=st2.split()
>>> n=2
>>> [(s, s in st1) for s in (' '.join(li[i:i+n]) for i in range(len(li)-n+1))]
[('B D', False), ('D E', True)]
如果你想要索引(任何一种方法),你可以使用str.find:
>>> [(s, st1.find(s)) for s in (' '.join(li[i:i+n]) for i in range(len(li)-n+1))
... if s in st1]
[('D E', 6)]
对于逐字逐句的正则表达式,请确保使用单词边界锚:
>>> st='wordW wordX wordY wordZ'
>>> re.findall(r'(?=(\b\w+\s\b\w+))', st)
['wordW wordX', 'wordX wordY', 'wordY wordZ']
答案 1 :(得分:1)
你可以像这样建立ngrams:
a = 'this is an example, whatever'.split()
b = 'this is another example, whatever'.split()
def ngrams(string, n):
return set(zip(*[string[i:] for i in range(n)]))
def common_ngrams(string1, string2, n):
return ngrams(string1, n) & ngrams(string2, n)
结果:
print(common_ngrams(a, b, 2))
{('this', 'is'), ('example,', 'whatever')}
print(common_ngrams(a, b, 1))
{('this',), ('is',), ('example,',), ('whatever',)}
请注意,棘手的位在带有zip function
的ngrams函数中zip(*[string[i:] for i in range(n)]
这与
基本相同zip(string, string[1:], string[2:])
表示n = 3.
另请注意,我们正在使用多组元组,这是性能最佳的......
答案 2 :(得分:0)
假设您有两个字符串(对于每个只包含一个字母的字符串,这很容易解决)
a = 'this is a beautiful day'
b = 'this day is awful'
然后得到b的所有单词也属于你写的
x = [x for x in b.split() if x in a.split()]
现在x包含(在一行代码之后)
['this', 'day', 'is']
然后检查x的序列组合(从0向上len(x)
)是否属于b
for i in range(len(x)):
for j in range(i, len(x)+1):
word = ' '.join(x[i:j])
if word in b:
print(word)
Example以b
的相同顺序打印a
的{{1}}个单词的(order preservig)组合(在{{1}中进行小调整嵌套for)的语句
答案 3 :(得分:0)
longest common substring algorithm将在这里工作,如果你传入一个拆分列表而不是一个普通的字符串 - 还有额外的奖励,如果你传入的话,它还会给出最长的字符串中最长的字符串。未分裂的字符串。
def longest_common_substring(s1, s2):
m = [[0] * (1 + len(s2)) for i in xrange(1 + len(s1))]
longest, x_longest = 0, 0
for x in xrange(1, 1 + len(s1)):
for y in xrange(1, 1 + len(s2)):
if s1[x - 1] == s2[y - 1]:
m[x][y] = m[x - 1][y - 1] + 1
if m[x][y] > longest:
longest = m[x][y]
x_longest = x
else:
m[x][y] = 0
return s1[x_longest - longest: x_longest]