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

Как я могу изменить этот список так, чтобы все 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']

Ответы

Ответ 1

Вы можете использовать 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 который будет использоваться для сортировки элементов в списке, как указано в документации:

Значением параметра key должна быть функция, которая принимает один аргумент и возвращает ключ для использования в целях сортировки.

Таким образом, принимая во внимание, что 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')]

Ответ 2

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

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']

Ответ 3

Используйте 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']

Ответ 4

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

>>> 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.

Ответ 5

Вы можете найти все элементы 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']

Ответ 6

Вы также можете сохранить свои передние, средние и конечные значения в 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']

Ответ 7

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

  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