5

私は文字列と辞書を持っています。そのテキスト内のすべての辞書キーを置き換える必要があります。

text = 'I have a smartphone and a Smart TV'
dict = {
    'smartphone': 'toy',
    'smart tv': 'junk'
}

キーにスペースがない場合は、テキストを単語に分割し、 dict と 1 つずつ比較します。O(n)かかったように見えます。しかし、今ではキーの中にスペースができているので、物事はより複雑です。これを行う良い方法を教えてください。キーとテキストの大文字と小文字が一致しない場合があることに注意してください。

アップデート

私はこの解決策を考えましたが、効率的ではありません。O(m*n) 以上...

for k,v in dict.iteritems():
    text = text.replace(k,v) #or regex...
4

5 に答える 5

2

テキスト内のキーワードが互いに近くない場合 (keyword other keyword)、これを行うことがあります。O(n) かかった >"<

def dict_replace(dictionary, text, strip_chars=None, replace_func=None):
    """
        Replace word or word phrase in text with keyword in dictionary.

        Arguments:
            dictionary: dict with key:value, key should be in lower case
            text: string to replace
            strip_chars: string contain character to be strip out of each word
            replace_func: function if exist will transform final replacement.
                          Must have 2 params as key and value

        Return:
            string

        Example:
            my_dict = {
                "hello": "hallo",
                "hallo": "hello",    # Only one pass, don't worry
                "smart tv": "http://google.com?q=smart+tv"
            }
            dict_replace(my_dict, "hello google smart tv",
                         replace_func=lambda k,v: '[%s](%s)'%(k,v))
    """

    # First break word phrase in dictionary into single word
    dictionary = dictionary.copy()
    for key in dictionary.keys():
        if ' ' in key:
            key_parts = key.split()
            for part in key_parts:
                # Mark single word with False
                if part not in dictionary:
                    dictionary[part] = False

    # Break text into words and compare one by one
    result = []
    words = text.split()
    words.append('')
    last_match = ''     # Last keyword (lower) match
    original = ''       # Last match in original
    for word in words:
        key_word = word.lower().strip(strip_chars) if \
                   strip_chars is not None else word.lower()
        if key_word in dictionary:
            last_match = last_match + ' ' + key_word if \
                         last_match != '' else key_word
            original = original + ' ' + word if \
                       original != '' else word
        else:
            if last_match != '':
                # If match whole word
                if last_match in dictionary and dictionary[last_match] != False:
                    if replace_func is not None:
                        result.append(replace_func(original, dictionary[last_match]))
                    else:
                        result.append(dictionary[last_match])
                else:
                    # Only match partial of keyword
                    match_parts = last_match.split(' ')
                    match_original = original.split(' ')
                    for i in xrange(0, len(match_parts)):
                        if match_parts[i] in dictionary and \
                           dictionary[match_parts[i]] != False:
                            if replace_func is not None:
                                result.append(replace_func(match_original[i], dictionary[match_parts[i]]))
                            else:
                                result.append(dictionary[match_parts[i]])
            result.append(word)
            last_match = ''
            original = ''

    return ' '.join(result)
于 2016-02-04T19:04:00.187 に答える
1

キーにスペースがない場合:

output = [dct[i] if i in dct else i for i in text.split()]

' '.join(output)

組み込み関数 dict() と衝突しないように、dict の代わりに dct を使用する必要があります。

これは、辞書内包表記と三項演算子 を使用してデータをフィルタリングします。

キーにスペースが含まれている場合は、正しいです。

for k,v in dct.iteritems():
    string.replace('d', dct[d])

はい、今回は、dct のキーごとに毎回文字列を反復処理する必要があるため、複雑さは m*n になります。

于 2016-02-02T02:00:23.080 に答える
0

1 (個々の単語) から len(text) (文字列全体) までのすべての隣接順列をテストする必要があります。次の方法で隣接順列を生成できます。

text = 'I have a smartphone and a Smart TV'

array = text.lower().split()

key_permutations = [" ".join(array[j:j + i]) for i in range(1, len(array) + 1) for j in range(0, len(array) - (i - 1))]

>>> key_permutations
['i', 'have', 'a', 'smartphone', 'and', 'a', 'smart', 'tv', 'i have', 'have a', 'a smartphone', 'smartphone and', 'and a', 'a smart', 'smart tv', 'i have a', 'have a smartphone', 'a smartphone and', 'smartphone and a', 'and a smart', 'a smart tv', 'i have a smartphone', 'have a smartphone and', 'a smartphone and a', 'smartphone and a smart', 'and a smart tv', 'i have a smartphone and', 'have a smartphone and a', 'a smartphone and a smart', 'smartphone and a smart tv', 'i have a smartphone and a', 'have a smartphone and a smart', 'a smartphone and a smart tv', 'i have a smartphone and a smart', 'have a smartphone and a smart tv', 'i have a smartphone and a smart tv']

次に、辞書を使用して置き換えます。

import re

for permutation in key_permutations:
    if permutation in dict:
        text = re.sub(re.escape(permutation), dict[permutation], text, flags=re.IGNORECASE)

>>> text
'I have a toy and a junk'

逆の順序で並べ替えを試してみることをお勧めしますが、最も長いものから順に並べ替えて、より具体的なフレーズが個々の単語よりも優先されるようにします。

于 2016-02-02T04:42:05.287 に答える
0

すべての辞書キーと入力テキストを小文字にすると、比較が簡単になります。今 ...

for entry in my_dict:
    if entry in text:
        # process the match

これは、辞書が一致を保証するのに十分小さいことを前提としています。代わりに、辞書が大きく、テキストが小さい場合は、各単語、次に各 2 単語の句を取得して、それらが辞書にあるかどうかを確認する必要があります。

それはあなたを動かすのに十分ですか?

于 2016-02-02T02:02:29.007 に答える