Joe*_*ult 6 python grouping parsing
不知道如何标题这个问题.我遇到过一些情况,我有一个数据列表,可能带有一些属性注释,我想将它们收集到组中.
例如,也许我有这样的文件:
some event
reading: 25.4
reading: 23.4
reading: 25.1
different event
reading: 22.3
reading: 21.1
reading: 26.0
reading: 25.2
another event
reading: 25.5
reading: 25.1
Run Code Online (Sandbox Code Playgroud)
并且我想对每组读数进行分组,将它们分成条件(在这种情况下,发生事件),这样我最终得到的结构就像
[['some event',
'reading: 25.4',
'reading: 23.4',
'reading: 25.1'],
['different event',
'reading: 22.3',
'reading: 21.1',
'reading: 26.0',
'reading: 25.2'],
['another event',
'reading: 25.5',
'reading: 25.1']]
Run Code Online (Sandbox Code Playgroud)
在它的通用形式中,它是:查找条件,收集数据直到该条件再次为真,重复
现在,我会做类似的事情
events = []
current_event = []
for line in lines:
if is_event(line):
if current_event:
events.append(current_event)
current_event = [line]
else:
current_event.append(line)
else:
if current_event:
events.append(current_event)
def is_event(line):
return 'event' in line
Run Code Online (Sandbox Code Playgroud)
它产生了我想要的东西,但它很丑陋且难以理解.我相当肯定必须有更好的方法
我的猜测是它涉及一些itertools魔法,但我是itertools的新手并不能完全包围所有这些.
谢谢!
我实际上已经和史蒂夫杰索普的Grouper课程一起回答了.这是我正在做的事情:
class Grouper(object):
def __init__(self, condition_function):
self.count = 0
self.condition_function = condition_function
def __call__(self, line):
if self.condition_function(line):
self.count += 1
return self.count
Run Code Online (Sandbox Code Playgroud)
然后像它一样使用它
event_grouper = Grouper(is_event)
result_as_iterators = (x[1] for x in itertools.groupby(lines, event_grouper))
Run Code Online (Sandbox Code Playgroud)
然后把它变成我做的字典
event_dictionary = [{event: readings} for event, *readings in result_as_iterators]
Run Code Online (Sandbox Code Playgroud)
这使
[
{'some event': ['reading: 25.4', 'reading: 23.4', 'reading: 25.1']},
{'different event': ['reading: 22.3','reading: 21.1','reading: 26.0','reading: 25.2']},
{'another event': ['reading: 25.5', 'reading: 25.1']}
]
Run Code Online (Sandbox Code Playgroud)
我怀疑itertools(或集合)可以使它更清晰,除非确切的模式在那里实现.
我注意到两件事:
current_event[0]因此,如果您有当前事件,则可以跳过检查,并且您也不必创建特殊情况.另外,由于"当前"事件总是最后一个,我们可以使用负索引直接跳转到它:
events = []
for line in lines:
if is_event(line):
events.append([])
events[-1].append(line)
def is_event(line):
return 'event' in line
Run Code Online (Sandbox Code Playgroud)
有了itertools.groupby,您可以根据键轻松地对事物进行分组'event' in line.所以,作为第一步:
>>> for k, g in itertools.groupby(lines, lambda line: 'event' in line):
... print(k, list(g))
Run Code Online (Sandbox Code Playgroud)
当然,这并不是将事件与其价值观结合在一起.我怀疑你真的不希望事件与它们的值一起,但实际上更喜欢有一个event: [values]或一个列表(event, [values]).在这种情况下,你差不多完成了.例如,要获得该dict,只需使用石斑鱼配方(或zip(*[iter(groups)]*2))分组成对,然后使用dict理解来映射k, v这些对next(k): list(v).
在另一方面,如果你真的不希望他们在一起,这是相同的步骤,但用列表[next(k)] + list(v)]的末尾.
但是,如果你不真正了解groupby不够好,把这一描述成代码,你应该写的东西你就明白了.这并不太难:
def groupify(lines):
event = []
for line in lines:
if 'event' in line:
if event: yield event
event = [line]
else:
event.append(line)
if event: yield event
Run Code Online (Sandbox Code Playgroud)
是的,它是7行(可以通过一些技巧缩小到4行)而不是3行(通过嵌套理解以丑陋的方式缩小为1),但是你理解并且可以调试的7行比3行魔法更有用.
迭代由此函数创建的生成器时,它会为您提供行列表,如下所示:
>>> for event in groupify(lines):
... print(event)
Run Code Online (Sandbox Code Playgroud)
这将打印:
['some event', 'reading: 25.4', 'reading: 23.4', 'reading: 25.1']
['different event', 'reading: 22.3', 'reading: 21.1', 'reading: 26.0', 'reading: 25.2']
['another event', 'reading: 25.5', 'reading: 25.1']
Run Code Online (Sandbox Code Playgroud)
如果你想要一个列表而不是一个生成器(所以你可以索引它,或者迭代它两次),你可以做同样的事情来将任何其他的iterable转换成一个列表:
events = list(groupify(lines))
Run Code Online (Sandbox Code Playgroud)
您可以利用 Python 中的函数具有状态这一事实。此石斑鱼功能与 DSM 的功能相同accumulate(fn(line) for line in s1):
def grouper(line):
if is_event(line):
grouper.count += 1
return grouper.count
grouper.count = 0
result_as_iterators = (x[1] for x in itertools.groupby(lines, grouper))
Run Code Online (Sandbox Code Playgroud)
然后如果你需要它:
result_as_lists = [list(x) for x in result_as_iterators]
Run Code Online (Sandbox Code Playgroud)
为了允许并发使用,每次使用时都需要一个新的石斑鱼函数对象(以便它有自己的计数)。您可能会发现将其设为一个类更简单:
class Grouper(object):
def __init__(self):
self.count = 0
def __call__(self, line):
if is_event(line):
self.count += 1
return self.count
results_as_iterators = itertools.groupby(lines, Grouper())
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
249 次 |
| 最近记录: |