Разделение Python для списков
Если у нас есть list
of strings
в python и вы хотите создать подсписок на основе специальных string
, как это сделать?
Например:
l = ["data","more data","","data 2","more data 2","danger","","date3","lll"]
p = split_special(l,"")
будет генерировать:
p = [["data","more data"],["data 2","more data 2","danger"],["date3","lll"]]
Ответы
Ответ 1
itertools.groupby - это один из подходов (как это часто бывает):
>>> l = ["data","more data","","data 2","more data 2","danger","","date3","lll"]
>>> from itertools import groupby
>>> groupby(l, lambda x: x == "")
<itertools.groupby object at 0x9ce06bc>
>>> [list(group) for k, group in groupby(l, lambda x: x == "") if not k]
[['data', 'more data'], ['data 2', 'more data 2', 'danger'], ['date3', 'lll']]
Мы можем даже немного обмануть из-за этого конкретного случая:
>>> [list(group) for k, group in groupby(l, bool) if k]
[['data', 'more data'], ['data 2', 'more data 2', 'danger'], ['date3', 'lll']]
Ответ 2
Одна возможная реализация с использованием itertools
>>> l
['data', 'more data', '', 'data 2', 'more data 2', 'danger', '', 'date3', 'lll']
>>> it_l = iter(l)
>>> from itertools import takewhile, dropwhile
>>> [[e] + list(takewhile(lambda e: e != "", it_l)) for e in it_l if e != ""]
[['data', 'more data'], ['data 2', 'more data 2', 'danger'], ['date3', 'lll']]
Примечание *
Это работает так же быстро, как с помощью groupby
>>> stmt_dsm = """
[list(group) for k, group in groupby(l, lambda x: x == "") if not k]
"""
>>> stmt_ab = """
it_l = iter(l)
[[e] + list(takewhile(lambda e: e != "", it_l)) for e in it_l if e != ""]
"""
>>> t_ab = timeit.Timer(stmt = stmt_ab, setup = "from __main__ import l, dropwhile, takewhile")
>>> t_dsm = timeit.Timer(stmt = stmt_dsm, setup = "from __main__ import l, groupby")
>>> t_ab.timeit(100000)
1.6863486541265047
>>> t_dsm.timeit(100000)
1.5298066765462863
>>> t_ab.timeit(100000)
1.735611326163962
>>>
Ответ 3
reduce
приходит на ум:
def split(iterable, where):
def splitter(acc, item, where=where):
if item == where:
acc.append([])
else:
acc[-1].append(item)
return acc
return reduce(splitter, iterable, [[]])
data = ["data","more data","","data 2","more data 2","danger","","date3","lll"]
print split(data, '')
Результат:
[['data', 'more data'], ['data 2', 'more data 2', 'danger'], ['date3', 'lll']]
Ответ 4
Я не уверен, что это самый "питонический" способ его решения.
def split_seq(seq, sep):
start = 0
while start < len(seq):
try:
stop = start + seq[start:].index(sep)
yield seq[start:stop]
start = stop + 1
except ValueError:
yield seq[start:]
break
ll = ["data","more data","","data 2","more data 2","danger","","date3","lll"]
p = [i for i in split_seq(ll,"")]
Ответ 5
Есть одна идея.:)
def spec_split(seq,sep):
# Ideally this separator will never be in your list
odd_sep = "[email protected]#$%^&*()"
# Join all the items with the odd separator and split
# anywhere the odd separator + separator + odd seperator meet
# This makes a list of items broken by the separator
jumble = odd_sep.join(seq).split(odd_sep+sep+odd_sep)
# split the remaining items broken by odd separators into sublists
return [item.split(odd_sep) for item in jumble]
Ответ 6
lst = ["data","more data","","data 2","more data 2","danger","","date3","lll"]
join_list = ",".join(lst)
split_list = join_list.split(",,")
result = [i.split() for i in split_list]
#result =[['data,more', 'data'], ['data', '2,more', 'data', '2,danger'], ['date3,lll']]