[英]Get the string that is the midpoint between two other strings
是否有可用的库或代码片段可以包含两个字符串,并返回两个字符串之间的精确或近似中点字符串?
最好的代码是用Python。
从表面上看,这似乎是一个简单的问题,但我对此颇为挣扎:
U+0088 c2 88 <control>
我问的原因是因为我希望编写map-reduce类型算法来从数据库中读取所有条目并进行处理。 数据库中的主键是UTF-8编码的字符串,具有随机字符分布。 我们正在使用的数据库是Cassandra。
希望从数据库中获取最低键和最高键,然后通过找到中点将其分为两个范围,然后通过找到它们的每个中点将这两个范围分为两个较小的部分,直到我拥有几千个为止部分,然后我可以异步读取每个部分。
如果字符串是以base-16编码的示例:(某些中点是近似值):
Starting highest and lowest keys: '000' 'FFF' / \ / \ '000' '8' '8' 'FFF' / \ / \ / \ / \ Result: '000' '4' '4' '8' '8' 'B8' 'B8' 'FFF' (After 3 levels of recursion)
不幸的是, 并非所有字节序列都是有效的UTF-8,因此仅取UTF-8值的中点并不是一件容易的事,如下所示。
def midpoint(s, e):
'''Midpoint of start and end strings'''
(sb, eb) = (int.from_bytes(bytes(x, 'utf-8'), byteorder='big') for x in (s, e))
midpoint = int((eb - sb) / 2 + sb)
midpoint_bytes = midpoint.to_bytes((midpoint.bit_length() // 8) + 1, byteorder='big')
return midpoint_bytes.decode('utf-8')
基本上,此代码将每个字符串转换为由内存中的字节序列表示的整数,找到这两个整数的中点,然后尝试再次将“中点”字节解释为UTF-8。
根据您确切想要的行为,下一步可能是用某种替换字符替换midpoint_bytes
的无效字节,以形成有效的UTF-8字符串。 对于您的问题,只要您保持一致,使用哪个字符替换就可能无关紧要。
但是,由于您正在尝试对数据进行分区,并且似乎不太在乎中点的字符串表示形式,因此另一种选择是将中点表示形式保留为整数,并在进行分区时将键转换为整数。 根据您问题的严重程度,此选项可能可行或不可行。
这是一个通用解决方案,它给出任意两个Unicode字符串a
和b
之间的近似中点m
,如果可能的话, a < m < b
:
from os.path import commonprefix
# This should be set according to the range and frequency of
# characters used.
MIDCHAR = u'm'
def midpoint(a, b):
prefix = commonprefix((a, b))
p = len(prefix)
# Find the codepoints at the position where the strings differ.
ca = ord(a[p]) if len(a) > p else None
cb = ord(b[p])
# Find the approximate middle code point.
cm = (cb // 2 if ca is None else (ca + cb) // 2)
# If a middle code point was found, add it and return.
if ca < cm < cb:
return prefix + unichr(cm)
# If b still has more characters after this, then just use
# b's code point and return.
if len(b) > p + 1:
return prefix + unichr(cb)
# Otherwise, if cb == 0, then a and b are consecutive so there
# is no midpoint. Return a.
if cb == 0:
return a
# Otherwise, use part of a and an extra character so that
# the result is greater than a.
i = p + 1
while i < len(a) and a[i] >= MIDCHAR:
i += 1
return a[:i] + MIDCHAR
该函数假定a < b
。 除此之外,它还可以使用任意Unicode字符串,甚至包含u'\\x00'
字符的字符串。 还要注意,它可能返回包含u'\\x00'
或其他非标准代码点的字符串。 如果没有中点由于b == a + u'\\x00'
然后a
返回。
如果您查看JAVA StringTokinizer方法,它将执行您想要的操作,甚至更多。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.