对字符串进行排序。保留每个字符串的前 X 个字符。如果此前缀对于前后的字符串不是唯一的,则前进直到找到唯一字符(与之前和之后的字符串相比)。(如果没有找到唯一字符,则字符串没有唯一部分,请参阅帖子底部)在这些唯一字符之前和之后添加省略号。
请注意,这仍然看起来很有趣:
Microsoft Office -> Micro...ffice
Microsoft Outlook -> Micro...utlook
我不知道您要使用哪种语言来执行此操作,但这是一个 Python 实现。
def unique_index(before, current, after, size):
'''Returns the index of the first part of _current_ of length _size_ that is
unique to it, _before_, and _after_. If _current_ has no part unique to it,
_before_, and _after_, it returns the _size_ letters at the end of _current_'''
before_unique = False
after_unique = False
for i in range(len(current)-size):
#this will be incorrect in the case mentioned below
if i > len(before)-1 or before[i] != current[i]:
before_unique = True
if i > len(after)-1 or after[i] != current[i]:
after_unique = True
if before_unique and after_unique:
return i
return len(current)-size
def ellipsize(entries, prefix_size, max_string_length):
non_prefix_size = max_string_length - prefix_size #-len("...")? Post isn't clear about this.
#If you want to preserve order then make a copy and make a mapping from the copy to the original
entries.sort()
ellipsized = []
# you could probably remove all this indexing with something out of itertools
for i in range(len(entries)):
current = entries[i]
#entry is already short enough, don't need to truncate
if len(current) <= max_string_length:
ellipsized.append(current)
continue
#grab empty strings if there's no string before/after
if i == 0:
before = ''
else:
before = entries[i-1]
if i == len(entries)-1:
after = ''
else:
after = entries[i+1]
#Is the prefix unique? If so, we're done.
current_prefix = entries[i][:prefix_size]
if not before.startswith(current_prefix) and not after.startswith(current_prefix):
ellipsized.append(current[:max_string_length] + '...') #again, possibly -3
#Otherwise find the unique part after the prefix if it exists.
else:
index = prefix_size + unique_index(before[prefix_size:], current[prefix_size:], after[prefix_size:], non_prefix_size)
if index == prefix_size:
header = ''
else:
header = '...'
if index + non_prefix_size == len(current):
trailer = ''
else:
trailer = '...'
ellipsized.append(entries[i][:prefix_size] + header + entries[i][index:index+non_prefix_size] + trailer)
return ellipsized
另外,您提到字符串本身是独一无二的,但是它们都有独特的部分吗?例如,“Microsoft”和“Microsoft Internet Explorer 7”是两个不同的字符串,但第一个字符串没有与第二个字符串不同的部分。如果是这种情况,那么您必须在规范中添加一些内容,以说明如何使这种情况明确。(如果将“Xicrosoft”、“MXcrosoft”、“MiXrosoft”等添加到这两个字符串的混合中,则没有比原始字符串更短的唯一字符串来表示“Microsoft”)(另一种思考方式:如果你有所有可能的 X 字母字符串,你不能将它们全部压缩为 X-1 或更少的字符串。就像没有压缩方法可以压缩所有输入一样,
原始帖子的结果:
>>> for entry in ellipsize(["Microsoft Internet Explorer 6", "Microsoft Internet Explorer 7", "Microsoft Internet Explorer 8", "Mozilla Firefox 3", "Mozilla Firefox 4", "Google Chrome 14"], 7, 20):
print entry
Google Chrome 14
Microso...et Explorer 6
Microso...et Explorer 7
Microso...et Explorer 8
Mozilla Firefox 3
Mozilla Firefox 4
>>> for entry in ellipsize(["Minutes of Company Meeting, 5/25/2010 -- Internal use only", "Minutes of Company Meeting, 6/24/2010 -- Internal use only", "Minutes of Company Meeting, 7/23/2010 -- Internal use only"], 15, 40):
print entry
Minutes of Comp...5/25/2010 -- Internal use...
Minutes of Comp...6/24/2010 -- Internal use...
Minutes of Comp...7/23/2010 -- Internal use...