группировать и классифицировать слова, а также символы - PullRequest
0 голосов
/ 01 ноября 2018

Мне нужно разделить на слеш, а затем сообщить теги. Это формат словаря Hunspell. Я пытался найти класс на github, который бы делал это, но не смог его найти.

# vi test.txt
test/S
boy
girl/SE
home/
house/SE123
man/E
country
wind/ES

код:

from collections import defaultdict
myl=defaultdict(list)

with open('test.txt') as f :
    for l in f:
        l = l.rstrip()
        try:
            tags = l.split('/')[1]
            myl[tags].append(l.split('/')[0])
            for t in tags:
                myl[t].append( l.split('/')[0])
        except:
            pass

Выход:

defaultdict(list,
            {'S': ['test', 'test', 'girl', 'house', 'wind'],
             'SE': ['girl'],
             'E': ['girl', 'house', 'man', 'man', 'wind'],
             '': ['home'],
             'SE123': ['house'],
             '1': ['house'],
             '2': ['house'],
             '3': ['house'],
             'ES': ['wind']})

В группе SE должно быть 3 слова «девушка», «ветер» и «дом». Не должно быть группы ES, потому что она включена и такая же, как "SE", а SE123 должен оставаться как есть. как мне этого добиться?


Обновление:

Мне удалось добавить биграммы, но как мне добавить 3, 4, 5 грамма?

from collections import defaultdict
import nltk
myl=defaultdict(list)

with open('hi_IN.dic') as f :
    for l in f:
        l = l.rstrip()
        try:
            tags = l.split('/')[1]
            ntags=''.join(sorted(tags))
            myl[ntags].append(l.split('/')[0])
            for t in tags:
                myl[t].append( l.split('/')[0])
            bigrm = list(nltk.bigrams([i for i in tags]))
            nlist=[x+y for x, y in bigrm]
            for t1 in nlist:
                t1a=''.join(sorted(t1))
                myl[t1a].append(l.split('/')[0])
        except:
            pass

Полагаю, было бы полезно отсортировать теги по источнику:

with open('test1.txt', 'w') as nf:
    with open('test.txt') as f :
        for l in f:
            l = l.rstrip()
            try:
                tags = l.split('/')[1]
            except IndexError:
                nline= l 
            else:
                ntags=''.join(sorted(tags))
                nline= l.split('/')[0] + '/' + ntags
            nf.write(nline+'\n')

Это создаст новый файл test1.txt с отсортированными тегами. Но проблема триграмм + до сих пор не решена.


Я скачал образец файла:

! Wget https://raw.githubusercontent.com/wooorm/dictionaries/master/dictionaries/en-US/index.dic

Отчет с использованием команды "grep" правильный.

!grep 'P.*U' index1.dic

CPU/M
GPU
aware/PU
cleanly/PRTU
common/PRTUY
conscious/PUY
easy/PRTU
faithful/PUY
friendly/PRTU
godly/PRTU
grateful/PUY
happy/PRTU
healthy/PRTU
holy/PRTU
kind/PRTUY
lawful/PUY
likely/PRTU
lucky/PRTU
natural/PUY
obtrusive/PUY
pleasant/PTUY
prepared/PU
reasonable/PU
responsive/PUY
righteous/PU
scrupulous/PUY
seemly/PRTU
selfish/PUY
timely/PRTU
truthful/PUY
wary/PRTU
wholesome/PU
willing/PUY
worldly/PTU
worthy/PRTU

Отчет Python с использованием биграмм в файле отсортированных тегов не содержит всех слов, упомянутых выше.

myl['PU']

['aware',
 'aware',
 'conscious',
 'faithful',
 'grateful',
 'lawful',
 'natural',
 'obtrusive',
 'prepared',
 'prepared',
 'reasonable',
 'reasonable',
 'responsive',
 'righteous',
 'righteous',
 'scrupulous',
 'selfish',
 'truthful',
 'wholesome',
 'wholesome',
 'willing']

Ответы [ 3 ]

0 голосов
/ 12 ноября 2018

Попробуйте это:

myl=dict()
with open('test.txt') as f :
    for l in f:
        l = l.rstrip()
        try:
            tags = l.split('/')[1]
            myl.setdefault(tags,[])
            myl[tags].append(l.split('/')[0])
            for t in tags:
                myl.setdefault(t,[])
                myl[t].append( l.split('/')[0])
        except:
            pass
keys=myl.keys()
for k1 in keys:
    for k2 in keys:
        if len(set(k1).intersection(k2))==len(set(k1)) and k1!=k2:
            myl[k1].extend([myk2v for myk2v in myl[k2] if myk2v not in myl[k1]]) 
print(myl)

выход

{'S': ['test', 'test', 'girl', 'house', 'wind'], 'SE': ['girl', 'house', 'wind'], 'E': ['girl', 'house', 'man', 'man', 'wind'], '': ['home', 'test', 'test', 'girl', 'house', 'wind', 'man', 'man'], 'SE123': ['house'], '1': ['house'], '2': ['house'], '3': ['house'], 'ES': ['wind', 'girl', 'house']}

В двух последних циклах программы сначала выбираются наборы k1 и k2, а затем сравнивается пересечение двух наборов. Если длина пересечения равна длине множества k1, значение ключа k2 должно быть в ключе k1, поэтому значение ключа k2 добавляется к ключу k1.

0 голосов
/ 13 ноября 2018

Гораздо более простая версия того, что Виллем ван Онсем уже ответил

data = defaultdict(list)
with open('text.txt') as f:
    for line in f.readlines():
        try:
            element,tags = line.rstrip().split('/', 1)
            print(element)
            for tag in tags:
                data[tag].append(element)
                data[None].append(element)
        except ValueError:
            pass

def parse(data,tag):
    if(tag==None or tag==''):
        return set(data[None])
    elements = [set(data[tag_i]) for tag_i in tag]
    return set.intersection(*map(set, elements))



>>> parse(data,'ES') 
>>> {'girl', 'house', 'wind'}
>>> parse(data,None)
>>> {'girl', 'house', 'man', 'wind'}
>>> parse(data,'')
>>> {'girl', 'house', 'man', 'wind'}
0 голосов
/ 10 ноября 2018

Если я правильно понимаю, это скорее вопрос создания структуры данных, которая для данного тега создает правильный список. Мы можем сделать это, создав словарь, который учитывает только особые теги. Позже, когда человек запрашивает несколько тегов, мы вычисляем пересечение. Таким образом, это делает его компактным для представления, а также простым для извлечения, например, всех элементов с тегом AC, и это будет перечислять элементы с тегом ABCD, ACD, ZABC и т. Д.

Таким образом, мы можем построить парсер:

from collections import defaultdict

class Hunspell(object):

    def __init__(self, data):
        self.data = data

    def __getitem__(self, tags):
        if not tags:
            return self.data.get(None, [])

        elements = [self.data.get(tag ,()) for tag in tags]
        data = set.intersection(*map(set, elements))
        return [e for e in self.data.get(tags[0], ()) if e in data]

    @staticmethod
    def load(f):
       data = defaultdict(list)
       for line in f:
           try:
               element, tags = line.rstrip().split('/', 1)
               for tag in tags:
                   data[tag].append(element)
               data[None].append(element)
           except ValueError:
               pass  # element with no tags
       return Hunspell(dict(data))

Обработка списка в конце __getitem__ выполняется для извлечения элементов в правильном порядке.

Затем мы можем загрузить файл в память с помощью:

>>> with open('test.txt') as f:
...     h = Hunspell.load(f)

и запросить его для произвольных ключей:

>>> h['SE']
['girl', 'house', 'wind']
>>> h['ES']
['girl', 'house', 'wind']
>>> h['1']
['house']
>>> h['']
['test', 'girl', 'home', 'house', 'man', 'wind']
>>> h['S3']
['house']
>>> h['S2']
['house']
>>> h['SE2']
['house']
>>> h[None]
['test', 'girl', 'home', 'house', 'man', 'wind']
>>> h['4']
[]

запрос несуществующих тегов приведет к пустому списку. Здесь мы, таким образом, откладываем процесс «пересечения» после вызова. Фактически мы уже можем генерировать все возможные пересечения, но это приведет к большой структуре данных и, возможно, к большому количеству работы

...