Применять элементы в начале и в конце списка

Как я могу изменить этот список так, чтобы все p's отображались в начале, q's в конце, а значения между ними были отсортированы в алфавитном порядке?

l = ['f','g','p','a','p','c','b','q','z','n','d','t','q']

Итак, я бы хотел иметь:

['p','p','a','b','c','d','f','g','n','t','z','q','q']
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
28
0
1 605
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

Используйте параметр key в отсортированный:

l = ['f','g','p','a','p','c','b','q','z','n','d','t','q']

def key(c):
    if c == 'q':
        return (2, c)
    elif c == 'p':
        return (0, c)
    return (1, c)


result = sorted(l, key=key)
print(result)

Вывод

['p', 'p', 'a', 'b', 'c', 'd', 'f', 'g', 'n', 't', 'z', 'q', 'q']
Ответ принят как подходящий

Вы можете использовать sorted со следующим key:

sorted(l, key = lambda s: (s!='p', s=='q', s))
['p', 'p', 'a', 'b', 'c', 'd', 'f', 'g', 'n', 't', 'z', 'q', 'q']

Объяснение

Чтобы лучше понять, как это работает, следующее понимание списка нацелено на воспроизведение того, что возвращается функцией lambda, определенной в аргументе key, до проведения сравнений:

t = [(s!='p', s=='q', s) for s in pl]

print(t)
[(True, False, 'f'),
 (True, False, 'g'),
 (False, False, 'p'),
 (True, False, 'a'),
 (False, False, 'p'),
 (True, False, 'c'),
 (True, False, 'b'),
 (True, True, 'q'),
 (True, False, 'z'),
 (True, False, 'n'),
 (True, False, 'd'),
 (True, False, 't'),
 (True, True, 'q')]

Затем это будет key, который будет использоваться для сортировки элементов в списке, как указано в документация:

The value of the key parameter should be a function that takes a single argument and returns a key to use for sorting purposes.

Итак, учитывая False = 0 и True = 1, при сортировке этого списка кортежей результат будет следующим:

sorted(t)
[(False, False, 'p'),
 (False, False, 'p'),
 (True, False, 'a'),
 (True, False, 'b'),
 (True, False, 'c'),
 (True, False, 'd'),
 (True, False, 'f'),
 (True, False, 'g'),
 (True, False, 'n'),
 (True, False, 't'),
 (True, False, 'z'),
 (True, True, 'q'),
 (True, True, 'q')]

Это довольно круто. Вы можете немного объяснить? отсортированные сортировки Истина <символы <Ложь?

Scott Boston 27.12.2018 17:24

@ScottBoston нет, он возвращает кортеж (bool, bool, str)

juanpa.arrivillaga 27.12.2018 17:26

@ juanpa.arrivillaga А ... Хорошо. Думаю, я понимаю. Я собираюсь немного поиграть с этим, чтобы закрепить это в моей голове. Спасибо.

Scott Boston 27.12.2018 17:27

Итак, сначала идет (Ложь, Ложь), а в конце - (Истина, Истина). Между ними будет (Верно, Ложь)

yatu 27.12.2018 17:27

Для тех из вас, кому нужен этот sorted([(s!='p', s=='q', s) for s in l]), он отлично наглядно показывает, что происходит.

Scott Boston 27.12.2018 17:33

Вы можете найти все элементы p и q, отфильтровать исходный список, а затем отсортировать:

l = ['f','g','p','a','p','c','b','q','z','n','d','t','q']
_ps, _qs = [i for i in l if i == 'p'], [i for i in l if i == 'q']
new_l = _ps+sorted(filter(lambda x:x not in {'q', 'p'}, l))+_qs

Вывод:

['p', 'p', 'a', 'b', 'c', 'd', 'f', 'g', 'n', 't', 'z', 'q', 'q']
Если, вы собираетесь сделать это таким образом, вы также можете просто посчитать p и q: ['p']*l.count('p') + sorted(filter({'q', 'p'}.isdisjoint, l)) + ['q']*l.count('q'), что имеет такую ​​же временную сложность. Редактировать: От lambda тоже можно избавиться.
pault 27.12.2018 17:26

Просто определите соответствующую ключевую функцию:

>>> def _key(x):
...     if x == 'p':
...         return -1
...     elif x == 'q':
...         return float('inf')
...     else:
...         return ord(x)
...
>>> l = ['f','g','p','a','p','c','b','q','z','n','d','t','q']
>>> sorted(l, key=_key)
['p', 'p', 'a', 'b', 'c', 'd', 'f', 'g', 'n', 't', 'z', 'q', 'q']

Обратите внимание, что каждый символ отображается в целое число> = 0, поэтому мы можем просто полагаться на ord, и поскольку -1 всегда будет меньше, чем все, что возвращается ord, мы можем использовать это для p, а для q мы можем использовать бесконечность, так что он всегда будет больше, чем то, что возвращает ord.

Одна из идей - использовать словарь приоритетов с настраиваемой функцией. Это, естественно, можно расширить, если вы захотите включить дополнительные критерии.

L = ['f','g','p','a','p','c','b','q','z','n','d','t','q']

def sort_func(x):
    priority = {'p': 0, 'q': 2}
    return priority.get(x, 1), x

res = sorted(L, key=sort_func)

print(res)

['p', 'p', 'a', 'b', 'c', 'd', 'f', 'g', 'n', 't', 'z', 'q', 'q']

Вы также можете сохранить переднюю, середину и концы в collections.defaultdict(), а затем просто добавить все три списка в конце:

from collections import defaultdict

l = ["f", "g", "p", "a", "p", "c", "b", "q", "z", "n", "d", "t", "q"]

keys = {"p": "front", "q": "end"}

d = defaultdict(list)
for item in l:
    d[keys.get(item, "middle")].append(item)

print(d["front"] + sorted(d["middle"]) + d["end"])
# ['p', 'p', 'a', 'b', 'c', 'd', 'f', 'g', 'n', 't', 'z', 'q', 'q']

Решение этого вопроса:

  1. Сначала найдите все элементы p и q в списке.
  2. Отфильтруйте исходный список.
  3. Затем, наконец, отсортируйте список.

list = ['f','g','p','a','p','c','b','q','z','n','d','t','q'];
noOfPs = [i for i in l if i == 'p']; 
noOfQs = [i for i in l if i == 'q'];
resultList= noOfPs + sorted(filter(lambda x:x not in {'q', 'p'}, l))+ noOfQs 

Вы можете использовать следующую функцию lambda в качестве ключа в sorted():

l1 = sorted(l, key=lambda x: ((x == 'q') - (x == 'p'), x))

print(l1)
# ['p', 'p', 'a', 'b', 'c', 'd', 'f', 'g', 'n', 't', 'z', 'q', 'q']

Функция генерирует следующие ключи сравнения:

func = lambda x: ((x == 'q') - (x == 'p'), x)

for i in l1:
    print(func(i))

Вывод:

(-1, 'p')
(-1, 'p')
(0, 'a')
(0, 'b')
...
(0, 't')
(0, 'z')
(1, 'q')
(1, 'q')

Другие вопросы по теме