对单词和字符进行分组和分类

时间:2018-11-01 07:58:00

标签: python nltk hunspell

我需要在斜杠上分开然后报告标记。这是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个单词“ girl”,“ wind”和“ house”。应该没有ES组,因为包含了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。但是trigrams +的问题仍然没有解决。


我下载了一个示例文件:

!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

在分类标签文件上使用bigrams的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 :(得分:5)

鉴于我正确理解,这更多的是构建一个数据结构,对于给定的标签,该数据结构构造正确的列表。我们可以通过构造仅考虑单数标记的字典来做到这一点。稍后,当一个人查询多个标签时,我们将计算交集。因此,这使得它的表示形式紧凑,并且易于提取所有带有标签AC的元素,这将列出带有标签ABCDACDZABC的元素等

因此,我们可以构造一个解析器:

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']
[]

查询不存在的标签将导致一个空列表。因此,这里我们在调用时推迟了“交叉点”过程。实际上,我们已经可以生成所有可能的交集,但这将导致庞大的数据结构,甚至可能需要大量工作

答案 1 :(得分:2)

尝试一下:

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']}

在程序的最后两个for循环中,首先获取k1k2的集合,然后比较这两个集合的交集。如果相交的长度等于集合k1的长度,则键{{1​​}}的值应在键k2中,因此键{{1}的值}添加到键k1中。

答案 2 :(得分:1)

willem van onsem已经回答的简单得多的版本

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'}