python: пользовательская сортировка: не чисто лексикографическая, а обратная и самая короткая общая сначала

Фон

Я хочу отсортировать наоборот, но не строго лексикографически, и тогда это становится еще более странным..: P

Причина в том, что проприетарное программное обеспечение анализирует каталоги именно так, как я здесь описываю, и я хочу скопировать это поведение.

Требования (в таком порядке)

  1. оба: совместимы с python2 и python3
  2. Обратный лексикографический
  3. самый короткий общий первый

Пример данных

Ниже приведен пример (случайно упорядоченных) входных данных для этого скрипта Python:

IA-test-PROD-me
ia-test-prod-me
ia-test-me-staging
ia-test-me
ia-test-STAGING-me
IA-test-me
IA-test-me-staging
ia-test-me-prod
IA-test-me-STAGING
IA-test-me-prod
IA-test-me-PROD
IA-test-STAGING-me

Как это должно выглядеть

Я храню это в списке, и мне нужно отсортировать его, чтобы он выглядел в конце так:

ia-test-me
ia-test-prod-me
ia-test-me-staging
ia-test-me-prod
ia-test-STAGING-me
IA-test-me
IA-test-me-staging
IA-test-me-prod
IA-test-me-STAGING
IA-test-me-PROD
IA-test-STAGING-me
IA-test-PROD-me

Код

Насколько я понял, sort() и sorted() - это стабильные функции, которые сортируются лексикографически. Но поскольку мне нужно выполнить все вышеперечисленные требования, я застрял на месте.

def sortLexo(input_list):
    words = input_list.split()
    words.sort(reverse=True)
 
    for i in words:
        print(i)

Проблема в том, что одного sort() + reverse=True недостаточно, так как он не выполняет требование 3 (сначала самое короткое):

           <-------------. should be placed here
ia-test-prod-me          |
ia-test-me-staging      /|\
ia-test-me-prod          |
ia-test-me    -------> wrong
ia-test-STAGING-me
           <--------------- should be placed here
IA-test-me-staging        |
IA-test-me-prod          /|\
IA-test-me-STAGING        |
IA-test-me-PROD           |
IA-test-me    --------> wrong
IA-test-STAGING-me
IA-test-PROD-me

Я играл с groupby для сортировки по длине, но ничего не получаю (мой python kl не такой глубокий) .. :(

Я думаю, это очень легко сделать для тех, кто хорошо знает, как python ... любая помощь приветствуется!


person xddev    schedule 10.11.2020    source источник
comment
Я не думаю, что ваш вопрос будет считаться стабильным, поскольку я думаю, что результат может зависеть от порядка ввода.   -  person Tim Ludwinski    schedule 10.11.2020
comment
ввод не должен иметь значения, так как он может быть случайным. сорт, который мне нужен, должен быть стабильным.   -  person xddev    schedule 10.11.2020
comment
Вы уверены, что ia-test-me должно быть выше ia-test-prod-me. Я думаю, что он должен быть под ним.   -  person Tim Ludwinski    schedule 11.11.2020
comment
да .. проприетарное программное обеспечение анализирует именно так .. как они применяют настройки или, лучше сказать, наследуют настройки конфигурации ..   -  person xddev    schedule 11.11.2020
comment
В вашем входном списке 9 элементов, в выходном примере 12 элементов… это не стабильная сортировка и не сортировка в целом.   -  person gboffi    schedule 11.11.2020
comment
извините, проблема с копированием/вставкой для списка входов. исправлено.   -  person xddev    schedule 12.11.2020


Ответы (1)


Пытаюсь собрать воедино по описанию. Похоже, вы хотите заполнить правую часть строки сравнения самым высоким символом, который вы ожидаете получить (я использую символ 0xFF, но если вы используете Unicode вместо ASCII, вам может понадобиться большее число).

MAX_LENGTH = max(len(word) for word in words)
sorted(words, key=lambda word: word + "\xFF" * (MAX_LENGTH - len(word)), reverse=True)

Это приведет к следующему. Хотя это отличается от вашего вопроса, я не могу понять, какая спецификация приведет к выводу в вопросе.

ia-test-prod-me
ia-test-me
ia-test-me-staging
ia-test-me-prod
ia-test-STAGING-me
IA-test-me
IA-test-me-staging
IA-test-me-prod
IA-test-me-STAGING
IA-test-me-PROD
IA-test-STAGING-me
IA-test-PROD-me

Код делает следующее: ключевая функция создала ключ для сравнения. В этом случае мы берем слово и дополняем его правую часть самым старшим символом, который мы ожидаем найти в строке; это код "\xFF" * (MAX_LENGTH - len(word)). Использование оператора умножения для строки может показаться странным, но он работает и создает строку той длины, на которую вы ее умножаете; в этом случае разница между максимальной длиной строки и длиной текущей строки. При обычной сортировке по алфавиту (как в словаре) более короткие слова идут первыми в порядке сортировки. Заполнение старшим символом заставляет строки, совпадающие до конца более короткой строки (например, ia-test-me и ia-test-me-staging), помещать более короткую строку последней (в данном случае первой, поскольку мы переворачиваем весь список с помощью reverse=True).

person Tim Ludwinski    schedule 10.11.2020
comment
вау, спасибо за этот быстрый ответ! › Я не могу понять, какая спецификация будет давать вывод в вопросе, когда проприетарное программное обеспечение анализирует каталоги таким образом, чтобы применить настройки или, что еще лучше, перезаписывает таким образом (ia-test-me-prod перезаписывает ia-test-me-staging и ia-test -me) извините за мое невежество, но не могли бы вы адаптировать приведенное выше к моему фрагменту кода выше? Я не уверен, как v и l относятся к моему коду: P извините, я python n00b :( - person xddev; 11.11.2020
comment
омг понял.. это просто: MAX_LENGTH = max(len(v) for v in words) sorted(words, key=lambda v: v + "\xFF" * (MAX_LENGTH - len(v)), reverse=True) . Это прекрасно работает! спасибо еще раз, вы спасли мой день! - person xddev; 11.11.2020
comment
можно ли объяснить, что именно делает ваш код? Я хочу понять, как это работает.. @tim-ludwinski - person xddev; 11.11.2020
comment
Я добавил объяснение внизу поста, а также обновил переменные l на words (как в вашем примере) и v на word. - person Tim Ludwinski; 11.11.2020
comment
Кроме того, данные вашего примера и то, как они должны выглядеть, имеют разную длину. - person Tim Ludwinski; 11.11.2020
comment
спасибо за объяснение! извините, проблема с копированием/вставкой для списка входов. исправлено. - person xddev; 12.11.2020
comment
нашел одну проблему, которую я только что обнаружил: в этом порядке And-test-me будет отображаться после IA-test-PROD-me, но это должно быть до IA. кажется, что порядок, который мне нужен, - это приоритет всех заглавных букв в первую очередь. так что иначе, чем в лексикографическом порядке, где он сравнивает символ за символом, он отдает приоритет IA над An .. черт .. есть идеи, как это можно решить? еще раз спасибо за вашу помощь здесь! - person xddev; 12.11.2020
comment
есть ли шанс для вышеупомянутого Тима? Я знаю, это странно, но я так застрял.. :((( - person xddev; 19.11.2020
comment
Если вы не определите, как именно должна работать сортировка, вы, возможно, никогда не сможете добиться того, чтобы что-то сортировалось таким образом. Что касается изменения сортировки, то в функции ключа сортировки можно вызвать функцию, которая изменит заглавные буквы на противоположные. Написание такой функции не должно быть слишком сложным (просто сделайте все строчные буквы заглавными, а все заглавные - строчными). - person Tim Ludwinski; 19.11.2020