将字符串与列表匹配以迭代检索

时间:2017-05-23 06:57:36

标签: python list

有两个列表,一个由句子的字符序列组成,另一个由单词组成。

目标是将第一个列表的项目与第二个列表的项目匹配length of li_a (len(li_a))次。相同的匹配单词将暂时保存为候选人。在最后的迭代过程之后,将选择最长的单词作为我们的预期结果,并将其附加到新的列表中。

由于<{1}}中有 18个字符,我们假设li_a 18

literation time

首先,li_a = ['T','h','o','m','a','s','h','a','d','a','h','a','r','d','t','i','m','e'] li_words = ['a','The','Thomas','have','had','has','hard','hot','time','tea'] 中的第一项与li_a匹配。

li_words

以上示例显示了应该如何完成第一个迭代过程。它为我们提供了一个候选结果,即1. 'T' => li_words || li_a[0] => li_words 2. 'Th' => li_words || li_a[0]+li_a[1] => li_words 3. 'Tho' => li_words || li_a[0]+li_a[1]+li_a[2] => li_words ... 6. 'Thomas' => li_words || li_a[0]+..+li_a[5] => li_words (marks as candidate when the match is found) ... 18. 'Thomashadahardtime' => li_words || li_a[0]..li_a[17] => li_words 。但是,从第一个'T'到's'(托马斯)Thomas项目将被扣除,

li_a

和第二个迭代过程一样,应该执行以检索下一个单词。

最后,我们列表的最终结果应该是这样的:

li_a = ['h','a','d','a','h','a','r','d','t','i','m','e']

尝试

以下尝试用于查找最长匹配,但不适用于迭代工作,并且在final_li = ['Thomas','had','a','hard','time']

中缺少单词时未提供准确结果
li_words

它返回为:def matched_substring(li1, li2): new_li = [] tmp = '' for a in li1: tmp += a count = 0 for b in li2: if tmp == b: count += 1 if count == 0: tmp1 = tmp.replace(a, '') new_li.append(tmp1) tmp = a if li2.__contains__(tmp): new_li.append(tmp) return new_li

UNICODE中的字符

['Thomas', 'h', 'a', 'd', 'a', 'h', 'a', 'r', 'd', 't', 'i', 'm']

将上面的String转换为List:

string_a = "['ဒီ|စစ်|ဆေး|မှု|ကို|သီး|ခြား|လွတ်|လပ်|တဲ့|ပု|ဂ္ဂို|လ်|တ|ဦး|က|ဦး|ဆောင်|ခိုင်း|တာ|ဟာ|လူ|ထု|အ|ကျိုး|အ|တွက်|ဖြစ်|တယ်|လို့|တ|ရား|ရေး|ဝန်|ကြီး|ဌာ|န|က|ထုတ်|ပြန်|တဲ့|ကြေ|ညာ|ချက်|ထဲ|မှာ|ဖေါ်|ပြ|ထား|ပါ|တယ်']"

链接到##Get rid of brackets & punctuation marks strp_str = string_a.strip("[]") strp_str = strp_str.strip("'") ##Now we achieve *li_a* li_a = strp_str.split('|') 列表的剪贴板:mm-words.txt

li_words

3 个答案:

答案 0 :(得分:2)

也许您可以尝试匹配li_a生成的字符串,例如

>>> li_a = ['T','h','o','m','a','s','h','a','d','a','h','a','r','d','t','i','m','e']
>>> li_words = ['a','The','Thomas','have','had','has','hard','hot','time','tea']
>>>
>>> s = "".join(li_a)
>>> for i in sorted(li_words,key=lambda x:-len(x)):
...     if i in s:
...         s=s.replace(i,str(li_words.index(i))+",")
...
>>> [li_words[int(i)] for i in s[:-1].split(",")]
['Thomas', 'had', 'a', 'hard', 'time']

希望这有帮助。

答案 1 :(得分:1)

为了获得所有可能的解决方案(如果还存在一些“重叠”单词),可以首先为每个单词找到可能出现该特定单词的所有起始位置。然后策略是从字符串的开头开始,测试所有可以出现在这里的候选者并在字符串中向前移动相应数量的字符。在这个新位置,重复该过程(由于递归,所有组合都被探索)。一旦我们到达字符串的末尾,就找到了一个成功的解决方案。

li_a = ['T', 'h','o','m','a','s','h','a','d','a','h','a','r','d','t','i','m','e','a']
li_words = ['a','The','Thomas','have','had','has','hard','hot','time','tea','timea']


def analyze(li_a, li_words):

    s = ''.join(li_a)

    #for each word, find all its positions in s
    stat = {}
    for word in li_words:
        pos = s.find(word)
        while pos != -1:
            if not pos in stat:
                stat[pos] = []
            stat[pos].append(word)
            pos = s.find(word, pos + 1)

    solutions = []

    def check(idx, solution):
        if idx == len(s):
            solutions.append(solution)
            return

        #at position idx, test all candidates and call
        #itself recursively
        words = stat.get(idx, [])
        for word in words:
            check(idx + len(word), solution + [word])

    #start at the beginning
    check(0, [])

    return solutions

print(analyze(li_a, li_words))

修改

我测试了您的Unicode输入,似乎string_a包含ဖေါ်中缺少的单词mm-words.txt。另一方面,无论如何,所提出的解决方案在这种情况下都会失败。首先,pos = s.find(word, pos + len(word))中存在错误,它应该是pos = s.find(word, pos + 1),以便找到特定单词的所有重叠事件。更重要的是,令人憎恶的复杂性要求(基本上是指数缩放)使得它在如此大的输入上无法使用。要走的路是采用dynamic programming approach。在下面的示例中,我只从string_a中获取前10个单词(保存到str.txt)以避免丢失的单词:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

def read_data(fname, delim, uniq = False):
    with open(fname, 'r') as F:
        data = F.read().split(delim)
        data = map(lambda s: s.decode('utf-8').strip(), data)
        data = filter(lambda s: s, data)
        if uniq:
            data = list(set(data))
    return data

li_a = read_data('str.txt', '|')
li_words = read_data('mm-words.txt', '\n', uniq = True)

def analyze(li_a, li_words):
    words = set(li_words)

    s = ''.join(li_a[0:10])
    N = len(s)

    solutions = [ [] for idx in range(0, N) ]
    S = [False for idx in range(0, N)]

    for i in range(0, N):
        flag = False
        if (s[0:i+1] in words):
            flag = True
            solutions[i].append([s[0:i+1], -1])

        else:
            for j in range(1, i+1):
                if S[j-1] and (s[j:i+1] in words):
                    #save the newly identified word and reference to solution
                    #previously found at location j-1
                    solutions[i].append([s[j:i+1], j-1])

                    #break #find only one solution
                    flag = True
        S[i] = flag

    splittings = []
    def assemble(pos, L):
        if pos == -1:
            splittings.append(L)
            return
        for w,idx in solutions[pos]:
            assemble(idx, [w] + L)

    assemble(N-1, [])
    return splittings

splittings = analyze(li_a, li_words)
for splitting in splittings:
    print(' | '.join(splitting).encode('utf-8'))

这会产生:

ဒီ | စစ်ဆေး | မှု | ကို | သီးခြား | လွတ်လပ် | တဲ့
ဒီ | စစ် | ဆေး | မှု | ကို | သီးခြား | လွတ်လပ် | တဲ့
ဒီ | စ | စ် | ဆေး | မှု | ကို | သီးခြား | လွတ်လပ် | တဲ့
ဒီ | စစ်ဆေး | မှု | ကို | သီး | ခြား | လွတ်လပ် | တဲ့
ဒီ | စစ် | ဆေး | မှု | ကို | သီး | ခြား | လွတ်လပ် | တဲ့
ဒီ | စ | စ် | ဆေး | မှု | ကို | သီး | ခြား | လွတ်လပ် | တဲ့
ဒီ | စစ်ဆေး | မှု | ကို | သီးခြား | လွတ် | လပ် | တဲ့
ဒီ | စစ် | ဆေး | မှု | ကို | သီးခြား | လွတ် | လပ် | တဲ့
ဒီ | စ | စ် | ဆေး | မှု | ကို | သီးခြား | လွတ် | လပ် | တဲ့
ဒီ | စစ်ဆေး | မှု | ကို | သီး | ခြား | လွတ် | လပ် | တဲ့
ဒီ | စစ် | ဆေး | မှု | ကို | သီး | ခြား | လွတ် | လပ် | တဲ့
ဒီ | စ | စ် | ဆေး | မှု | ကို | သီး | ခြား | လွတ် | လပ် | တဲ့
ဒီ | စစ်ဆေး | မှု | ကို | သီးခြား | လွ | တ် | လပ် | တဲ့
ဒီ | စစ် | ဆေး | မှု | ကို | သီးခြား | လွ | တ် | လပ် | တဲ့
ဒီ | စ | စ် | ဆေး | မှု | ကို | သီးခြား | လွ | တ် | လပ် | တဲ့
ဒီ | စစ်ဆေး | မှု | ကို | သီး | ခြား | လွ | တ် | လပ် | တဲ့
ဒီ | စစ် | ဆေး | မှု | ကို | သီး | ခြား | လွ | တ် | လပ် | တဲ့
ဒီ | စ | စ် | ဆေး | မှု | ကို | သီး | ခြား | လွ | တ် | လပ် | တဲ့
ဒီ | စစ်ဆေး | မှု | ကို | သီးခြား | လွတ် | လ | ပ် | တဲ့
ဒီ | စစ် | ဆေး | မှု | ကို | သီးခြား | လွတ် | လ | ပ် | တဲ့
ဒီ | စ | စ် | ဆေး | မှု | ကို | သီးခြား | လွတ် | လ | ပ် | တဲ့
ဒီ | စစ်ဆေး | မှု | ကို | သီး | ခြား | လွတ် | လ | ပ် | တဲ့
ဒီ | စစ် | ဆေး | မှု | ကို | သီး | ခြား | လွတ် | လ | ပ် | တဲ့
ဒီ | စ | စ် | ဆေး | မှု | ကို | သီး | ခြား | လွတ် | လ | ပ် | တဲ့
ဒီ | စစ်ဆေး | မှု | ကို | သီးခြား | လွ | တ် | လ | ပ် | တဲ့
ဒီ | စစ် | ဆေး | မှု | ကို | သီးခြား | လွ | တ် | လ | ပ် | တဲ့
ဒီ | စ | စ် | ဆေး | မှု | ကို | သီးခြား | လွ | တ် | လ | ပ် | တဲ့
ဒီ | စစ်ဆေး | မှု | ကို | သီး | ခြား | လွ | တ် | လ | ပ် | တဲ့
ဒီ | စစ် | ဆေး | မှု | ကို | သီး | ခြား | လွ | တ် | လ | ပ် | တဲ့
ဒီ | စ | စ် | ဆေး | မှု | ကို | သီး | ခြား | လွ | တ် | လ | ပ် | တဲ့

答案 2 :(得分:0)

这里有一个使用itertools的功能方法:

import itertools
li_a = ['T','h','o','m','a','s','h','a','d','a','h','a','r','d','t','i','m','e']
li_words = ['a','The','Thomas','have','had','has','hard','hot','time','tea']
res = list(itertools.imap(lambda x: max(itertools.ifilter(lambda y: x in y, li_words), key=len), li_a))
res
['Thomas', 'Thomas', 'Thomas', 'Thomas', 'Thomas', 'Thomas', 'Thomas', 'Thomas', 'hard', 'Thomas', 'Thomas', 'Thomas', 'hard', 'hard', 'time', 'time', 'Thomas', 'have']

我们的想法是,对于li_a中的每个字母,我们会过滤掉li_words这个字母的单词,然后使用max在该集合上使用len来获取最大的一个。

这里匹配压缩每个字母:

zip(li_a, res)
[('T', 'Thomas'), ('h', 'Thomas'), ('o', 'Thomas'), ('m', 'Thomas'), ('a', 'Thomas'), ('s', 'Thomas'), ('h', 'Thomas'), ('a', 'Thomas'), ('d', 'hard'), ('a', 'Thomas'), ('h', 'Thomas'), ('a', 'Thomas'), ('r', 'hard'), ('d', 'hard'), ('t', 'time'), ('i', 'time'), ('m', 'Thomas'), ('e', 'have')]