[英]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.