Храните похожие части нескольких строк, удалите части, которые отличаются в python [duplicate]

  1. Вам нужно только указать IBOutlet один раз, метку IBOutlet, что ваш ivar не нужен.
  2. Создаете ли вы свой NIB с помощью UIViewController? В какой-то момент вы должны называть [SecondView initWithNibName:@"yourNibName" bundle:nil];
38
задан thefourtheye 21 May 2015 в 07:30
поделиться

11 ответов

Его называют самой длинной общей проблемой подстроки. Здесь я представляю простое, понятное, но неэффективное решение. Это потребует много времени для создания правильного вывода для больших строк, так как сложность этого алгоритма равна O (N ^ 2).

def longestSubstringFinder(string1, string2):
    answer = ""
    len1, len2 = len(string1), len(string2)
    for i in range(len1):
        match = ""
        for j in range(len2):
            if (i + j < len1 and string1[i + j] == string2[j]):
                match += string2[j]
            else:
                if (len(match) > len(answer)): answer = match
                match = ""
    return answer

print longestSubstringFinder("apple pie available", "apple pies")
print longestSubstringFinder("apples", "appleses")
print longestSubstringFinder("bapples", "cappleses")

Выход

apple pie
apples
apples
18
ответ дан thefourtheye 20 August 2018 в 21:24
поделиться
  • 1
    Этот алгоритм является неправильным с учетом некоторых входов (например, «яблочный пирог ...», «яблочный пирог»), но работает, если вы переключаете положение параметра. Я думаю, что что-то не так с утверждением if, когда вы сравниваете i+j < len1 – REALFREE 9 July 2014 в 07:47
  • 2
    это работает для самого длинного префикса и перерывов на суффиксах. Например. x = "cov_basic_as_cov_x_gt_y_rna_genes_w1000000" y = "cov_rna15pcs_as_cov_x_gt_y_rna_genes_w1000000" – Dima Lituiev 22 February 2016 в 19:51
  • 3
    Если речь идет о поиске самой длинной общей подстроки, это будет излишним. Все, что вам нужно найти, если есть общая подстрока. Представление на основе суффикса-дерева будет эффективным способом поиска, если в данных двух строках есть общая. поиск будет O (m) сложностью, где m - длина более короткой строки. Для представления дерева требуется дополнительное хранилище. Мы могли бы оптимизировать хранилище, сохраняя только индексы в дереве, а не фактические символы. – lalatnayak 2 July 2017 в 19:37
  • 4
    это совершенно неправильно. попробуйте string1 = "2193588" , строка2 = "21943588" – Nozar Safari 14 February 2018 в 09:28

Попробуйте:

import itertools as it
''.join(el[0] for el in it.takewhile(lambda t: t[0] == t[1], zip(string1, string2)))

Выполняет сравнение с началом обеих строк.

1
ответ дан Birei 20 August 2018 в 21:24
поделиться
  • 1
    Теперь я хочу, чтобы python сделал функцию it.takewhile для языка: a for a, b in zip(string1, string2) while a == b – Eric 10 September 2013 в 12:23
  • 2
    ''.join(el[0] for el in itertools.takewhile(lambda t: t[0] == t[1], zip("ahello", "hello"))) возвращает "", что кажется неправильным. Правильный результат будет "hello". – Anderson Green 26 January 2015 в 06:43
  • 3
    @AndersonGreen: Вы правы, это не отвечает точно на вопрос, хотя на его примерах учитывалась только начальная точка первого символа, и я тоже указал на это в своем ответе. – Birei 26 January 2015 в 13:17

То же, что и Evo's , но с произвольным числом строк для сравнения:

def common_start(*strings):
    """ Returns the longest common substring
        from the beginning of the `strings`
    """
    def _iter():
        for z in zip(*strings):
            if z.count(z[0]) == len(z):  # check all elements in `z` are the same
                yield z[0]
            else:
                return

    return ''.join(_iter())
3
ответ дан Community 20 August 2018 в 21:24
поделиться
def matchingString(x,y):
    match=''
    for i in range(0,len(x)):
        for j in range(0,len(y)):
            k=1
            # now applying while condition untill we find a substring match and length of substring is less than length of x and y
            while (i+k <= len(x) and j+k <= len(y) and x[i:i+k]==y[j:j+k]):
                if len(match) <= len(x[i:i+k]):
                   match = x[i:i+k]
                k=k+1
    return match  

print matchingString('apple','ale') #le
print matchingString('apple pie available','apple pies') #apple pie     
0
ответ дан radhikesh93 20 August 2018 в 21:24
поделиться
def common_start(sa, sb):
    """ returns the longest common substring from the beginning of sa and sb """
    def _iter():
        for a, b in zip(sa, sb):
            if a == b:
                yield a
            else:
                return

    return ''.join(_iter())
>>> common_start("apple pie available", "apple pies")
'apple pie'

Или немного страннее:

def stop_iter():
    """An easy way to break out of a generator"""
    raise StopIteration

def common_start(sa, sb):
    return ''.join(a if a == b else stop_iter() for a, b in zip(sa, sb))

Что может быть более читаемым как

def terminating(cond):
    """An easy way to break out of a generator"""
    if cond:
        return True
    raise StopIteration

def common_start(sa, sb):
    return ''.join(a for a, b in zip(sa, sb) if terminating(a == b))
26
ответ дан Rahul K P 20 August 2018 в 21:24
поделиться
  • 1
    Это решение на данный момент не является полным. Он только сравнивает обе строки из нулевого положения. Например: & gt; & gt; & gt; & gt; & gt; common_start («XXXXXapple pie available», «apple pies») возвращает пустую строку. – Nitin Nain 7 September 2014 в 20:36
  • 2
    @NitinNain: Это не было выяснено в исходном вопросе. Но да, это решение находит только обычный start строк – Eric 7 September 2014 в 22:56
  • 3
    будет ли это работать один раз PEP479 ? – Janus Troelsen 19 August 2015 в 08:36
  • 4
    Нет - из , что документ : ». Также есть примеры выражений генератора, плавающих вокруг, которые полагаются на StopIteration, вызванные выражением, целью или предикатом ( а не вызовом __next __ (), подразумеваемым в правильном цикле for). & quot; – Eric 19 August 2015 в 20:11
  • 5
    @ Эрик все еще, из примечаний Python 3.6 , Raising the StopIteration exception inside a generator will now generate a DeprecationWarning. Если вы запускаете свой код с помощью Python3 -W default::DeprecationWarning, последние два примера поднимают DeprecationWarning s – jpyams 20 December 2017 в 17:10

Это не самый эффективный способ сделать это, но это то, что я мог придумать, и он работает. Если кто-то может его улучшить, пожалуйста. Что он делает, так это делает матрицу и ставит 1, где совпадают символы. Затем он сканирует матрицу, чтобы найти самую длинную диагональ 1 с, отслеживая, где она начинается и заканчивается. Затем он возвращает подстроку входной строки с начальным и конечным позициями в качестве аргументов.

Примечание. Это находит только одну самую длинную общую подстроку. Если есть более одного, вы можете создать массив для хранения результатов и вернуть его. Кроме того, он чувствителен к регистру, поэтому (Apple pie, apple pie) вернет pple pie.

def longestSubstringFinder(str1, str2):
answer = ""

if len(str1) == len(str2):
    if str1==str2:
        return str1
    else:
        longer=str1
        shorter=str2
elif (len(str1) == 0 or len(str2) == 0):
    return ""
elif len(str1)>len(str2):
    longer=str1
    shorter=str2
else:
    longer=str2
    shorter=str1

matrix = numpy.zeros((len(shorter), len(longer)))

for i in range(len(shorter)):
    for j in range(len(longer)):               
        if shorter[i]== longer[j]:
            matrix[i][j]=1

longest=0

start=[-1,-1]
end=[-1,-1]    
for i in range(len(shorter)-1, -1, -1):
    for j in range(len(longer)):
        count=0
        begin = [i,j]
        while matrix[i][j]==1:

            finish=[i,j]
            count=count+1 
            if j==len(longer)-1 or i==len(shorter)-1:
                break
            else:
                j=j+1
                i=i+1

        i = i-count
        if count>longest:
            longest=count
            start=begin
            end=finish
            break

answer=shorter[int(start[0]): int(end[0])+1]
return answer
1
ответ дан Rali Tsanova 20 August 2018 в 21:24
поделиться

Для полноты difflib в стандартной библиотеке содержится множество утилит сравнения последовательностей. Например, find_longest_match , который находит самую длинную общую подстроку при использовании в строках. Пример использования:

from difflib import SequenceMatcher

string1 = "apple pie available"
string2 = "come have some apple pies"

match = SequenceMatcher(None, string1, string2).find_longest_match(0, len(string1), 0, len(string2))

print(match)  # -> Match(a=0, b=15, size=9)
print(string1[match.a: match.a + match.size])  # -> apple pie
print(string2[match.b: match.b + match.size])  # -> apple pie
69
ответ дан RickardSjogren 20 August 2018 в 21:24
поделиться
  • 1
    @NorthSide Это должен быть принятый ответ – JPCF 15 July 2017 в 16:54
  • 2
    Загорается до тех, кто использует это на более длинных строках, вы можете захотеть установить kwarg-autojunk & quot; to False при создании экземпляра SequenceMatcher. – MLP 20 August 2018 в 03:57
  • 3
    – W4t3randWind 27 October 2018 в 16:18

Исправить ошибки с первым ответом:

def longestSubstringFinder(string1, string2):
    answer = ""
    len1, len2 = len(string1), len(string2)
    for i in range(len1):
        for j in range(len2):
            lcs_temp=0
            match=''
            while ((i+lcs_temp < len1) and (j+lcs_temp<len2) and string1[i+lcs_temp] == string2[j+lcs_temp]):
                match += string2[j+lcs_temp]
                lcs_temp+=1
            if (len(match) > len(answer)):
                answer = match
    return answer

print longestSubstringFinder("dd apple pie available", "apple pies")
print longestSubstringFinder("cov_basic_as_cov_x_gt_y_rna_genes_w1000000", "cov_rna15pcs_as_cov_x_gt_y_rna_genes_w1000000")
print longestSubstringFinder("bapples", "cappleses")
print longestSubstringFinder("apples", "apples")
0
ответ дан user7733798 20 August 2018 в 21:24
поделиться

Сначала функция помощника , адаптированная из парного рецепта itertools для создания подстрок.

import itertools
def n_wise(iterable, n = 2):
    '''n = 2 -> (s0,s1), (s1,s2), (s2, s3), ...

    n = 3 -> (s0,s1, s2), (s1,s2, s3), (s2, s3, s4), ...'''
    a = itertools.tee(iterable, n)
    for x, thing in enumerate(a[1:]):
        for _ in range(x+1):
            next(thing, None)
    return zip(*a)

Затем функция выполняет итерацию по подстрокам, самая длинная во-первых, и тесты для членства. (эффективность не учитывается)

def foo(s1, s2):
    '''Finds the longest matching substring
    '''
    # the longest matching substring can only be as long as the shortest string
    #which string is shortest?
    shortest, longest = sorted([s1, s2], key = len)
    #iterate over substrings, longest substrings first
    for n in range(len(shortest)+1, 2, -1):
        for sub in n_wise(shortest, n):
            sub = ''.join(sub)
            if sub in longest:
                #return the first one found, it should be the longest
                return sub

s = "fdomainster"
t = "exdomainid"
print(foo(s,t))

>>> 
domain
>>> 
0
ответ дан wwii 20 August 2018 в 21:24
поделиться

Возвращает первую длинную общую подстроку:

def compareTwoStrings(string1, string2):
    list1 = list(string1)
    list2 = list(string2)

    match = []
    output = ""
    length = 0

    for i in range(0, len(list1)):

        if list1[i] in list2:
            match.append(list1[i])

            for j in range(i + 1, len(list1)):

                if ''.join(list1[i:j]) in string2:
                    match.append(''.join(list1[i:j]))

                else:
                    continue
        else:
            continue

    for string in match:

        if length < len(list(string)):
            length = len(list(string))
            output = string

        else:
            continue

    return output
0
ответ дан xXDaveXx 20 August 2018 в 21:24
поделиться
0
ответ дан user3838498 31 October 2018 в 16:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: