#python #list #список #python_32
Python 3.2. Есть список lst, в котором есть значения вперемешку с элементами-разделителями. Например, ["spam", "ham", None, "eggs", None, None, "bacon"]. Хочу получить список списков, разбив lst по разделителю sep = None, т.е., получить [["spam", "ham"], ["eggs"], ["bacon"]]. Полистал стандартную библиотеку, но ничего похожего не нашел. На PyPi искать сложно, быстрый пробег тоже ничего не дал. Наглая попытка проэксплуатировать str.split, разумеется, провалилась с TypeError. Посоветуйте, пожалуйста, более красивое решение, чем вот этот вырвиглазный монстр. Не хочу ощущать себя Франкенштейном. from functools import reduce # Fugly. def split_on(sep, lst): """ Given an iterable `lst`, split it into iterable of lists by `sep`. >>> list(split_on(0, [1, 2, 3, 0, 4, 5, 0, 0, 6])) [[1, 2, 3], [4, 5], [6]] """ s = sep if hasattr(sep, "__call__") else lambda x: x == sep return filter(lambda sublist: len(sublist) > 0, reduce(lambda x, elem: x + [[]] if elem == sep else x[:-1] + [x[-1] + [elem]], lst, [[]]))
Ответы
Ответ 1
Судя по всему, функциональное программирование оставило на вас серьезный отпечаток :) Сразу отмечу, что семантика split для случая вашего примера подразумевает возврат [["spam", "ham"], ["eggs"], [], ["bacon"]]. Это так, поскольку между None и None с точки зрения разделителей располагается пустой список. Так вот, решений можно придумать несколько. Наиболее explicit вариант подразумевает что-то в следующем духе: def split_on(what, delimiter = None): splitted = [[]] for item in what: if item == delimiter: splitted.append([]) else: splitted[-1].append(item) return splitted Понятно, что это решение работает с точностью до контракта функции касательно работы в случае пустого списка - [] и списка, состоящего только из разделителя - [None]. Я определил этот контракт следующим образом: [ ] -> [[ ]], [None] -> [[], []]. Для первого случая контракт довольно спорный. Во втором же случае результат получается, поскольку слева и справа от разделителя по сути расположены пустые последовательности. В случае, если вы захотите изменить это поведение, то модифицировать метод не должно составить особого труда. Пример использования: list1 = ["spam", "ham", None, "eggs", None, None, "bacon"] list2 = [] list3 = [None] list4 = ["eggs"] print split_on(list1) print split_on(list2) print split_on(list3) print split_on(list4) # Результат: [['spam', 'ham'], ['eggs'], [], ['bacon']] [[]] [[], []] [['eggs']] Из альтернативных вариантов - можно написать аналогичный предложенной функции генератор с yield'ами и, думаю, что можно придумать решение, разбивая предложенную итерабельную последовательность на группы, а дальше объединяя результаты путем groupby из itertools. Правда, мне кажется, что очевидность этих решений по сравнению с предложенным выше методом будет несколько хуже.Ответ 2
m=["spam","ham","N","edg","N","N","back"] q=0 i=0 t=list(([],)*m.count("N")) for x in m: if x=="N": q=1 continue if q==1: i=i+1 t[i]=[] t[i].append(x) print(i,"---",t[i]) z=input() ============================= 0 --- ['spam'] 0 --- ['spam', 'ham'] 1 --- ['edg'] 2 --- ['back'] t=[['spam', 'ham'], ['edg'], ['back']]
Комментариев нет:
Отправить комментарий