Soru Karakterleri belirli anahtar kelimeler bir arada tutarken, bir dizeden bir Python listesi oluşturabilir misiniz?


Bir dizgedeki karakterlerden bir liste oluşturmak, ancak belirli anahtar kelimeleri birlikte tutmak istiyorum.

Örneğin:

anahtar kelimeler: araba, otobüs

GİRİŞ:

"xyzcarbusabccar"

ÇIKTI:

["x", "y", "z", "car", "bus", "a", "b", "c", "car"]

32
2018-02-07 21:40


Menşei




Cevaplar:


İle re.findall. Önce anahtar kelimeleriniz arasında geçiş yapın.

>>> import re
>>> s = "xyzcarbusabccar"
>>> re.findall('car|bus|[a-z]', s)
['x', 'y', 'z', 'car', 'bus', 'a', 'b', 'c', 'car']

Çakışan anahtar kelimeleriniz varsa, karşılaştığınız ilk sorunun bu çözümü bulacağını unutmayın:

>>> s = 'abcaratab'
>>> re.findall('car|rat|[a-z]', s)
['a', 'b', 'car', 'a', 't', 'a', 'b']

Çözümün yerini daha genel hale getirebilirsiniz. [a-z] neyi istersen, \w örneğin veya basit . herhangi bir karakteri eşleştirmek için.

Bu neden ve neden regex neden kısa açıklama '[a-z]|car|bus' işe yaramazsa: Normal ifade motoru, alternatif seçenekleri soldan sağa doğru çalışır ve "istekli"bir eşleşme döndürmek için. Bu, seçeneklerden biri tam olarak eşleştiğinde tüm alternasyonu eşleşmesi gerektiği anlamına gelir. Bu noktada, kalan seçeneklerden hiçbirini denemeyecektir, ancak işlemeyi durdurup hemen bir eşleşme bildirecektir. '[a-z]|car|bus'motor, [a-z] karakter sınıfında herhangi bir karakter gördüğünde bir eşleşme bildirecek ve 'araba' ya da 'otobüs'ün de eşleşip eşleşmeyeceğini kontrol etmek için asla yola çıkmayacaktır.


38
2018-02-07 21:43



Harika çözüm. kullanma '[a-z]|' + '|'.join(keywords) regex'i programlı olarak oluşturmayı kolaylaştırır. - SuperBiasedMan
@SuperBiasedMan Teşekkürler. Olurdu '|'.join(keywords) + '|[a-z]'Gerçi, regex motoru alternatifleri soldan sağa doğru dener ve istekli bir eşleşme döndürmek için. Bu yüzden çözüm işe yarıyor, belki de bir açıklamada düzenlemeliyim. - timgeb
Ah, aptal bana! Çok fazla regex kullanmıyorum ve sadece diğer sıranın daha okunabilir olacağını düşündüm. - SuperBiasedMan


s = "xyzcarbusabccar"
import re

print re.findall("bus|car|\w", s)
['x', 'y', 'z', 'car', 'bus', 'a', 'b', 'c', 'car']

Ya da belki \S herhangi bir boşluk olmayan chars için:

s = "xyzcarbusabccar!"
import re

print re.findall("bus|car|\S", s)
['x', 'y', 'z', 'car', 'bus', 'a', 'b', 'c', 'car', '!']

Sadece en uzun eşleşmeleri istiyorsanız, siparişi daha uzun kelimeleri koymanın doğru olduğundan emin ol.

In [7]: s = "xyzcarsbusabccar!"

In [8]: re.findall("bus|car|cars|\S", s)
Out[8]: ['x', 'y', 'z', 'car', 's', 'bus', 'a', 'b', 'c', 'car', '!']

In [9]: re.findall("bus|cars|car|\S", s)
Out[9]: ['x', 'y', 'z', 'cars', 'bus', 'a', 'b', 'c', 'car', '!']

16
2018-02-07 21:44





Yukarıdaki çözümler gerçekten harika, ancak anahtar kelimeler sözlüğü uzunsa, kolayca dağınık olabilir (belki de kabul edilemez).

Anahtar kelimeleri bir ağacın içinde saklamayı (gereksizliği sömüren) ve daha fazla alan verimli olmasını öneriyorum.

Anahtar kelimeler ["art,"at","atm","bus","can","car"] sözlük böyle görünüyor

                 .
                 ^
            /    ¦      \

          /      ¦        \
        a        b           c
        ^        ^           ^
      /   \       \           \
    r       t      u           a
    ^       ^      ^           ^
   /       /  \     \        /   \
  t       m   /0     s      n     r
  ^       ^          ^      ^     ^
 /      /             \      \     \
/0     /0             /0      /0   /0

Çizmeyi daha kolay olduğu için ikili yapıyorum. Düğüm "/0" kelime sonu (sanal karakter) ve "." Köktür.

Ağaç ve gerekli işlevleri oluşturmak için bu basit Tree sınıfını uyguladım

class Tree(object):

    def __init__(self, name='root', children=None):
        self.name = name
        self.children = {}
        if children is not None:
            for child in children:
                self.add_child(child.name,child)

    def __repr__(self):
        return self.name

    def add_child(self, node):
        assert isinstance(node, Tree)
        self.children[node.name] = node


    def has_child(self,name):
        return name in self.children

    def get_child(self,name):
        return self.children[name]

    def print_tree(self,level=0):
        sys.stdout.write('-' * level)
        print self.name
        for childTag in self.children:
            self.children[childTag].print_tree(level+1)

Anahtar kelimeler verildiğinde, bu gibi bir kod kullanarak yapıyı oluşturabiliriz

keywords = ["car","at","atm","bus"]
keywordsTree = Tree('')

for keyword in keywords:
    keywordsTreeNode = keywordsTree
    for character in keyword:
        if not keywordsTreeNode.has_child(character):
            keywordsTreeNode.add_child(Tree(character))
        keywordsTreeNode = keywordsTreeNode.get_child(character)

    keywordsTreeNode.add_child(Tree('/0'))

Son olarak, anahtar kelimeler için girdiyi araştırıyoruz. Aşağıdaki çözüm, bu pozisyondan başlayarak eşleşen tüm anahtar kelimelerin girişinde belirli bir pozisyon için teklif verir.

inputWords = "xyzcarbusabccar8hj/0atm"
output = []
lengthInput = len(inputWords)
for position in range(0,lengthInput):
    ##add by default the character
    # allMathcedKeyWords = [inputWords[position]]

    allMathcedKeyWords = []
    keywordsTreeNode = keywordsTree
    searchPosition = position
    curMathcedWord = ''

    while searchPosition < lengthInput and keywordsTreeNode.has_child(inputWords[searchPosition]) :

        keywordsTreeNode = keywordsTreeNode.get_child(inputWords[searchPosition])
        curMathcedWord = curMathcedWord + inputWords[searchPosition]

        if (keywordsTreeNode.has_child("/0")):
            allMathcedKeyWords.append(curMathcedWord)

        searchPosition += 1

    if len(allMathcedKeyWords)==0:
        allMathcedKeyWords = inputWords[position]

    output.append(allMathcedKeyWords)

print output

Bu kod bunu çıkarır

['x', 'y', 'z', 
 ['car'], 
 'a', 'r', 
 ['bus'], 
  'u', 's', 'a', 'b', 'c',   
 ['car'],
  'a', 'r', '8', 'h', 'j', '/', '0', 
 ['at', 'atm'], 
  't', 'm']

Yukarıdaki kod için önemli olan sözcüklerin sonunda sanal karakterin iki harf olmasıdır ("/0") ve asla eşleşmeyecek (kombinasyon, yukarıda belirtildiği gibi giriş dizisinde görünse bile). Ayrıca, herhangi bir dize karakterini (giriş ve anahtar kelimeler için) ele alır. re.findall() )

Bu çıktı listesinden ne yapmak istediğinize karar verebilirsiniz. Çözüm istiyorsanız re.findall Bir konum için en uzun eşleşen kelimeyi (veya anahtar kelimeler mantıksal sırasını temel alarak) bulun ve sözcüğün içerdiği karakter sayısını atlayın.

Sorunu daha da ileri götürdüğünüzde, girişteki her karakter bir köşe noktasıdır ve bir kelime bulduğunuzda, eşleşen kelimenin son karakterinden sonra ilgili konumdan bir sonraki köşe noktasına bir kenar ekleyin. En kısa yol algoritması size yukarıdaki çözümü tekrar verecektir. Çıktının bu şekilde yapılandırılması, tekrar alan verimliliğini getirir ve daha karmaşık algoritmalara kapıyı açar.

Örnek anahtar kelimeler "car" ve "art" ve sanat ve giriş dizisi "acart" Ortaya çıkan grafikler böyle görünüyor

             ______________
            ¦              ¦
- a -> c -> a -> r -> t ->
       ¦______________¦

Karmaşıklık analizi

Space : longest_word_length * number_of_letters_in_keywords
        input_length + input_length * input_length (worst case-fully connected graph)
Time  : input_length * longest_word_length
        input_length + input_length * input_length (worst case-fully connected graph)

0
2018-03-08 20:35