我有一个代码,梁孙实施了
#Created by Liang Sun in 2013
import re
import collections
import hashlib
class Simhash(object):
def __init__(self, value):
self.f = 64
self.reg = ur'[\w\ufb50-\ufdff]'
self.value = None
if isinstance(value, Simhash):
self.value = value.value
elif isinstance(value, basestring):
self.build_by_text(unicode(value))
elif isinstance(value, collections.Iterable):
self.build_by_features(value)
elif isinstance(value, long):
self.value = value
elif isinstance(value, Simhash):
self.value = value.hash
else:
raise Exception('Bad parameter')
def _slide(self, content, width=2):
return [content[i:i+width] for i in xrange(max(len(content)-width+1, 1))]
def _tokenize(self, content):
ans = []
content = ''.join(re.findall(self.reg, content))
ans = self._slide(content)
return ans
def build_by_text(self, content):
features = self._tokenize(content)
return self.build_by_features(features)
def build_by_features(self, features):
features = set(features) # remove duplicated features
hashs = [int(hashlib.md5(w.encode('utf-8')).hexdigest(), 16) for w in features]
v = [0]*self.f
for h in hashs:
for i in xrange(self.f):
mask = 1 << i
v[i] += 1 if h & mask else -1
ans = 0
for i in xrange(self.f):
if v[i] >= 0:
ans |= 1 << i
self.value = ans
def distance(self, another):
x = (self.value ^ another.value) & ((1 << self.f) - 1)
ans = 0
while x:
ans += 1
x &= x-1
return ans
我想将此代码用于阿拉伯语言文本,我向Lian Sun询问了这个问题,他说我应该用阿拉伯语代码点范围替换self.reg = ur'[\w\ufb50-\ufdff]'
。我搜索并找到the Arabic Unicode block on Wikipedia,但我不知道如何使用它。
任何帮助表示赞赏
答案 0 :(得分:0)
没有“阿拉伯语代码点范围”,而是有7个特定于阿拉伯语的块,以及阿拉伯语可能使用的其他块。有关它们的详细说明,请参见Arabic script in Unicode。
如果您想匹配ISO-8859-6中提供的阿拉伯字符,您只需要其中一个块的一部分,即0621-0652。
如果要匹配Unicode 1.0中可用的阿拉伯字符,那就是块0600-06FF,0750-077F和08A0-08FF。
如果你想要上下文变体,你还需要两个“表单形式”块(虽然其中一些实际上并没有被阿拉伯语使用,只有其他使用阿拉伯语脚本的语言 - 然后再次,你标记了你的问题波斯语...),FB50-FDFF和FE70-FEFF。您的原始代码与FB50-FDFF匹配这一事实意味着您需要这些。
最后,从Unicode 6.1开始,您可能需要或不需要另外两个范围,主要用于数学,10E60-10E7F和1EE00-1EEFF。
我猜你需要前5个区块,但不是最后两个区块,所以,而不是这个:
ur'[\w\ufb50-\ufdff]'
......这样做:
ur'[\w\u0600-\u06ff\u0750-\u077f\u08a0-\u08ff\ufb50-\ufdff\ufe70-\ufeff]'
但是,我不确定这是否能真正解决您的问题。原始代码使用re.findall
和表示形式将文本分解为标记 - 可能是一种分裂结束字符的hacky方式(它只适用于以非常特殊,过时的方式编码的文本...) 。将其更改为findall
每次运行的阿拉伯字符都会给你一个非常不同的结果。