Python 什么';找到两条线的交点的最佳方法是什么?

Python 什么';找到两条线的交点的最佳方法是什么?,python,string,performance,set,Python,String,Performance,Set,我需要找到两条线的交点。 断言: assert intersect(“测试”、“测试”)==列表(“测试”),“断言1” 断言相交(“测试”,“ta”)==列表(“t”),“断言2” 断言相交(“foo”、“fo”)==列表(“fo”),“断言3” 断言相交(“foobar”,“foo”)==列表(“foo”),“断言4” 我尝试了intersect函数的不同实现intersect将接收2个str参数,w和w2 列表理解。迭代并查找第二个字符串中出现的情况 返回[l代表w中的l,如果l代表w

我需要找到两条线的交点。 断言:

assert intersect(“测试”、“测试”)==列表(“测试”),“断言1”
断言相交(“测试”,“ta”)==列表(“t”),“断言2”
断言相交(“foo”、“fo”)==列表(“fo”),“断言3”
断言相交(“foobar”,“foo”)==列表(“foo”),“断言4”
我尝试了
intersect
函数的不同实现
intersect
将接收2个
str
参数,
w
w2


列表理解。迭代并查找第二个字符串中出现的情况

返回[l代表w中的l,如果l代表w2]
失败断言1和断言2,因为
w
中的多个t与
w2中的一个t匹配


设置交点。

返回列表(集合(w).交叉点(w2)
返回列表(集合(w)和集合(w2))
失败断言3和4,因为集合是唯一元素的集合
,重复的字母将被丢弃


迭代并计数。

out=“”
对于s1中的c:
如果c输入s2而不是c输入输出:
输出+=c
返回
失败,因为它还消除了重复项


difflib()

letters\u diff=difflib.ndiff(单词、非通配符\u字母)
字母_相交=[]
对于字母为_diff的l:
字母代码,字母=l[:2],l[2:]
如果字母_代码==“”:
字母\u交叉点。附加(字母)
返回字母
通过


difflib
有效,但有人能想出更好的优化方法吗

编辑:
该函数将返回一个字符列表。顺序并不重要。

这对于您的测试用例非常有效:

def intersect(haystack, needle):
    while needle:
        pos = haystack.find(needle)
        if pos >= 0:
            return list(needle)
        needle = needle[:-1]
    return []
但是,请记住,您的所有测试用例都是长而短,没有空的搜索项、空的搜索空间或不匹配项。

尝试以下方法:

def intersect(string1, string2): 
    common = []
    for char in set(string1):
        common.extend(char * min(string1.count(char), string2.count(char)))

    return common

注意:它不保留顺序(如果我记得
set()
正确,字母将按字母顺序返回)。但是,正如您在评论中所说,顺序无关紧要给出了两个字符串中所有n-gram的共现数:

from collections import Counter

def all_ngrams(text):
    ngrams = ( text[i:i+n] for n in range(1, len(text)+1)
                           for i in range(len(text)-n+1) )
    return Counter(ngrams)

def intersection(string1, string2):
    count_1 = all_ngrams(string1)
    count_2 = all_ngrams(string2)
    return count_1 & count_2   # intersection:  min(c[x], d[x])

intersection('foo', 'f') # Counter({'f': 1})
intersection('foo', 'o') # Counter({'o': 1})
intersection('foobar', 'foo') # Counter({'f': 1, 'fo': 1, 'foo': 1, 'o': 2, 'oo': 1})
intersection('abhab', 'abab') # Counter({'a': 2, 'ab': 2, 'b': 2})
intersection('achab', 'abac') # Counter({'a': 2, 'ab': 1, 'ac': 1, 'b': 1, 'c': 1})
intersection('test', 'ates') # Counter({'e': 1, 'es': 1, 's': 1, 't': 1, 'te': 1, 'tes': 1})

交叉点('aba','aca')
的预期输出是什么?
['a']
['a','a']
?那么
交叉点('ab','b')
呢?
[]
['b']
?这些仅仅是前缀吗?如果不是,那么顺序真的重要还是仅仅是计数?交叉点的可能重复('aba','aca')应该返回
['a','a']
交叉点('ab','b')
只是
['b']
是。@ReutSharabani,编辑了这个问题。不,顺序无关紧要。
交叉点('ab','abhab')
['ab','ab']
?不幸的是,测试用例没有接近覆盖所有需求。如果你阅读问题下面的注释,你应该会发现这并不是OP想要的。@Aran Fey编辑:)
list(set(list(str1))
可以是
list(set(str1))
。你在
else
分支中有一个打字错误(
string
而不是
string2
)。我很确定,没有理由一开始就使用整个
if…else
东西。最后,对两个字符串重复调用
str.count
会增加运行时的复杂性。您可以使用
collections.Counter
只计算一次所有字符。(并且您的代码在编辑之前有语法错误。)
min(string1.count(char)、str2.count(char))
@Aran Fey The if-else是获得最小长度字符串所必需的。如果我确定字符串的长度不同,我就不需要它,但我使用的是if-else。@Aran Fey No这是正确的。这是因为set()删除了重复的字符串,但我需要在计数时计数重复的字符。