【问题标题】:How to efficiently remove consecutive duplicate words or phrases in a string [duplicate]如何有效地删除字符串中连续重复的单词或短语[重复]
【发布时间】:2019-12-16 21:02:59
【问题描述】:

我有一个包含重复出现的短语的字符串,或者它甚至可能是一个连续出现多次的单词。

尝试了各种方法,但找不到更节省时间和空间的方法。

这是我尝试过的方法

  1. groupby()
  2. 重新
String = "what type of people were most likely to be able to be able to be able to be able to be 1.35 ?"
s1 = " ".join([k for k,v in groupby(String.replace("</Sent>","").split())])
s2 = re.sub(r'\b(.+)(\s+\1\b)+', r'\1', String)

在我的情况下,它们似乎都不起作用

我的预期结果:

what type of people were most likely to be able to be 1.35 ?

这些是我提到的一些帖子

  1. Is there a way to remove duplicate and continuous words/phrases in a string? - 不起作用
  2. How can I remove duplicate words in a string with Python? - 部分工作,但也需要对大字符串的最佳方式

请不要将我的问题标记为与上述帖子重复,因为我尝试了大多数实现但没有找到有效的解决方案。

【问题讨论】:

  • 感谢@hiroprotagonist,它有帮助,但它不能解决我的问题。
  • 我相信这是一个相当困难的问题,特别是因为字符串不受任何字符数的限制,并且您必须检查几乎每个组合是否重复出现。
  • @BlueRineS 是的,我同意,你有解决这个问题的方法可以帮助我吗?
  • 我不确定,也许我们需要在网上使用更好的搜索关键词。我猜有某种算法可以解决这个问题,但我们根本不知道它的名字。

标签: python python-3.x string


【解决方案1】:

我会采用这种创造性的方法来寻找不断增长的副本:

input = "what type of people were most likely to be able to be able to be able to be able to be 1.35 ?"
def combine_words(input,length):
    combined_inputs = []
    if len(splitted_input)>1:
        for i in range(len(input)-1):
            combined_inputs.append(input[i]+" "+last_word_of(splitted_input[i+1],length)) #add the last word of the right-neighbour (overlapping) sequence (before it has expanded), which is the next word in the original sentence
    return combined_inputs, length+1

def remove_duplicates(input, length):
    bool_broke=False #this means we didn't find any duplicates here
    for i in range(len(input) - length):
        if input[i]==input[i + length]: #found a duplicate piece of sentence!
            for j in range(0,length): #remove the overlapping sequences in reverse order
                del input[i + length - j]
            bool_broke = True
            break #break the for loop as the loop length does not matches the length of splitted_input anymore as we removed elements
    if bool_broke:
        return remove_duplicates(input, length) #if we found a duplicate, look for another duplicate of the same length
    return input

def last_word_of(input,length):
    splitted = input.split(" ")
    if len(splitted)==0:
        return input
    else:
        return splitted[length-1]

#make a list of strings which represent every sequence of word_length adjacent words
splitted_input = input.split(" ")
word_length = 1
splitted_input,word_length = combine_words(splitted_input,word_length)

intermediate_output = False

while len(splitted_input)>1:
    splitted_input = remove_duplicates(splitted_input,word_length) #look whether two sequences of length n (with distance n apart) are equal. If so, remove the n overlapping sequences
    splitted_input, word_length = combine_words(splitted_input,word_length) #make even bigger sequences
    if intermediate_output:
        print(splitted_input)
        print(word_length)
output = splitted_input[0] #In the end you have a list of length 1, with all possible lengths of repetitive words removed

输出流利的

what type of people were most likely to be able to be 1.35 ?

即使它不是所需的输出,我看不出它会如何识别删除之前出现 3 个位置的“to be”(长度为 2)。

【讨论】:

  • 同意你的回答。正如@ComplicatedPhenomenon 所述。
  • 如果不涉及语法,我认为没有比这更好的了。我会说选择你的答案。另请注意,如果问号将连接到句子的最后一个单词,这可能会带来一些麻烦,因为最后一个单词已被此更改,因此不会被视为重复单词。
  • 同意你的看法!关于时间复杂度的任何统计数据?
  • 我觉得您应该可以使用@SayanipDutta 提到的timeit 包自己计时。它的运行速度比其他答案稍慢。
【解决方案2】:

我很确定这种方法在 Python 3.7 中保持了顺序,我不确定旧版本。

String = "what type of people were most likely to be able to be able to be able to be able to be 1.35 ?"
unique_words = dict.fromkeys(String.split())
print(' '.join(unique_words))
>>> what type of people were most likely to be able 1.35 ?

【讨论】:

  • 这行得通,关于时间复杂度的任何信息?
  • 对,如果考虑到语法错误,likeString = "what type of people were most likely to be able to be able to work?"会变成what type of people were most likely to be able work?,问题就比较难了。
  • @ComplicatedPhenomenon 是的,这正是一个很好的例子,它在最后丢失了to
  • 是的,如果你合并语法是完全不同的球赛,我只是试图匹配 OP 的预期输出。顺便说一句,@Dev timeit 100000 次迭代给出0.25722896799925365 s
  • @SayandipDutta 好吧,我不希望它与语法合并,所以让我现在使用它。谢谢! ,如果不接受答案,将等待任何可以修复语法的不同方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-29
  • 1970-01-01
  • 2015-01-26
  • 1970-01-01
  • 2021-03-03
  • 1970-01-01
  • 2011-01-03
相关资源
最近更新 更多