Сортировка строк.Сохраните первые 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...