我有一个这样的清单:
[u'1.9', u'comment', u'1.11', u'1.5', u'another comment']
我想将它拆分为元组,使得数字字符串(isdigit(item[0])
为True
)与紧跟在它们之后的注释配对,或者如果没有则与空字符串配对注释(即,下一个项目是另一个数字字符串)。
换句话说:
[
(u'1.9', u'comment'),
(u'1.11', ''),
(u'1.5', u'another comment'),
]
最简洁的方法是什么,特别是因为列表可能是奇数甚至是长度?
答案 0 :(得分:2)
您最好的选择是使用生成器功能进行配对:
def number_paired(items):
items = iter(items)
number = next(items)
while number is not None:
comment = next(items, None)
if comment is None or comment[0].isdigit():
# really a number, or end of the iterable
yield number, u''
number = comment
continue
yield number, comment
number = next(items)
然后您可以迭代生成器或从中生成一个列表:
result = list(number_paired(items))
这也处理了最后有一个数字并且没有以下注释的情况:
>>> def number_paired(items):
... items = iter(items)
... number = next(items)
... while number is not None:
... comment = next(items, None)
... if comment is None or comment[0].isdigit():
... # really a number, or end of the iterable
... yield number, u''
... number = comment
... continue
... yield number, comment
... number = next(items)
...
>>> items = [u'1.9', u'comment', u'1.11', u'1.5', u'another comment']
>>> list(number_paired(items))
[(u'1.9', u'comment'), (u'1.11', u''), (u'1.5', u'another comment')]
>>> list(number_paired(items + [u'42']))
[(u'1.9', u'comment'), (u'1.11', u''), (u'1.5', u'another comment'), (u'42', u'')]
答案 1 :(得分:1)
以下是如何在单个列表理解中完成它。
my_list = [u'1.9', u'comment', u'1.11', u'1.5', u'another comment']
result = [(x,('' if i + 1 >= len(my_list) or my_list[i + 1].replace('.','').isdigit() else my_list[i + 1])) for i, x in enumerate(my_list) if x and x.replace('.','').isdigit()]
答案 2 :(得分:0)
我会这样做(pairwise
来自itertools
食谱):
input = [u'1.9', u'comment', u'1.11', u'1.5', u'another comment']
from itertools import tee, izip
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return izip(a, b)
import re
v_re = re.compile('\d\.\d+')
[(a, b) if not v_re.match(b) else (a, '') for a, b in pairwise(input + [u'']) if v_re.match(a)]
# [(u'1.9', u'comment'), (u'1.11', ''), (u'1.5', u'another comment')]
它应该适用于input
中的单个元素和以版本字符串结尾的input
。
答案 3 :(得分:0)
首先,“isdigit”只能看似测试整数,所以为简单起见我首先假设输入是:
>>> lst = [u'9', u'comment', u'11', u'1001', u'another comment']
然后解决方案是一个班轮:
>>> [(i, '') if s.isdigit() else (i, s) for i, s in zip(lst[:-1], lst[1:]) if i.isdigit()]
[(u'9', u'comment'), (u'11', ''), (u'1001', u'another comment')]
<强>解释强>
zip生成所有对,
>>> lst = ['a', 'b', 'c', 'd']
>>> zip(lst[:-1], lst[1:]
[('a', 'b'), ('b', 'c'), ('c', 'd')]
然后使用以下if语句以整数字符串过滤对。
>>> [(i, s) for i, s in zip(...) if i.isdigit()]
最后,使用if else语句生成结果,即(i,'')或(i,s)
顺便说一句,当lst中只有一个元素时,这不起作用。在这种情况下,你应该专门处理。