首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用groupby将3个元组列表转换为元组列表

如何使用groupby将3个元组列表转换为元组列表
EN

Stack Overflow用户
提问于 2019-11-20 16:50:04
回答 1查看 62关注 0票数 2

我下面有一根绳子

代码语言:javascript
复制
test = '''AWS-1 - opened at Jan 23 2010 10:30:08AM 
AWS-2 - opened at Jan 23 2010 11:04:56AM 
AWS-2 - closed at Jan 23 2010 1:18:32PM 
AWS-1 - closed at Jan 23 2010 9:43:44PM 
AWS-1 - opened at Feb 1 2010 12:40:28AM
AWS-1 - closed at Jan 23 2010 9:43:44PM
'''

我的密码

代码语言:javascript
复制
import re
from itertools import groupby
y = re.findall(r'\b(\w+-\d+)\s+-\s+(\w+[-.\w]+)\s+at\s+(\w+[\s:.\w]+)\n', test)
print (y)
for key, time in groupby(y,lambda z: y[2]):
for thing in y:
    print( (y[1], key))
print (" ")

我的出局

(('AWS-2', 'opened', 'Jan 23 2010 11:04:56AM '), ('AWS-2', 'closed', 'Jan 23 2010 1:18:32PM ')) (('AWS-2', 'opened', 'Jan 23 2010 11:04:56AM '), ('AWS-2', 'closed', 'Jan 23 2010 1:18:32PM ')) (('AWS-2', 'opened', 'Jan 23 2010 11:04:56AM '), ('AWS-2', 'closed', 'Jan 23 2010 1:18:32PM ')) (('AWS-2', 'opened', 'Jan 23 2010 11:04:56AM '), ('AWS-2', 'closed', 'Jan 23 2010 1:18:32PM ')) (('AWS-2', 'opened', 'Jan 23 2010 11:04:56AM '), ('AWS-2', 'closed', 'Jan 23 2010 1:18:32PM '))

预期的结果并不是AWS-1,而是到处AWS-2都来了

代码语言:javascript
复制
(('AWS-1', 'opened', 'Jan 23 2010 10:30:08AM '), ('AWS-1', 'closed', 'Jan 23 2010 9:43:44PM '))
(('AWS-1', 'opened', 'Feb 1 2010 12:40:28AM'), ('AWS-1', 'closed', 'Feb 23 2010 9:43:44PM'))
(('AWS-2', 'opened', 'Jan 23 2010 11:04:56AM '), ('AWS-2', 'closed', 'Jan 23 2010 1:18:32PM '))
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-11-21 15:59:34

您的请求尚不清楚,但您似乎希望根据参数创建打开-关闭对。

给定的

代码语言:javascript
复制
import re

import dateutil


records = """\
AWS-1 - opened at Jan 23 2010 10:30:08AM
AWS-2 - opened at Jan 23 2010 11:03:56AM
AWS-2 - closed at Jan 23 2010 1:18:32PM 
AWS-1 - closed at Feb 27 2010 9:32:50PM
AWS-1 - opened at Feb 1 2010 12:50:28AM
AWS-1 - closed at Jan 23 2010 9:32:50PM
"""

代码语言:javascript
复制
def splitlines(s: str) -> tuple:
    """Return tuples of parsed lines: id, status, time."""
    res = []

    for line in s.split("\n"):

        if not line:
            continue            
        parsed = tuple(map(str.strip, filter(None, re.split("(\s-\s)|(at)", line))))
        id_, _, status, _, time = parsed 
        data = id_, status, dateutil.parser.parse(time)
        res.append(data)

    return tuple(res)


def pairwise_records(s: str) -> list:
    """Return paired records according to id, status and time."""
    key = lambda x: (x[0], x[2], x[1])

    sorted_recs = ((i, s, str(t)) for i, s, t in sorted(splitlines(s), key=key))

    return list(zip(sorted_recs, sorted_recs))

Demo

代码语言:javascript
复制
pairwise_records(records)

输出

代码语言:javascript
复制
[(('AWS-1', 'opened', '2010-01-23 10:30:08'),
  ('AWS-1', 'closed', '2010-01-23 21:32:50')),
 (('AWS-1', 'opened', '2010-02-01 00:50:28'),
  ('AWS-1', 'closed', '2010-02-27 21:32:50')),
 (('AWS-2', 'opened', '2010-01-23 11:03:56'),
  ('AWS-2', 'closed', '2010-01-23 13:18:32'))]

详细信息

对OP的赞许之处在于用一个精细的正则表达式得到了一个部分的答案。事实证明,您可以使用更清晰的正则表达式和不使用groupby来更显式地完成这一任务。

splitlines

我们尝试将输入字符串解析为元组。我们使用re.split来完成这个任务,它留下了我们不需要的额外元素。这些附加部分使用filter进行清理,并将其解压缩到(id_, status, time)中,其中time被解析为datetime对象。结果是分析线的元组。示例:

代码语言:javascript
复制
splitlines("AWS-1 - opened at Jan 23 2010 10:30:08AM")
# (('AWS-1', 'opened', datetime.datetime(2010, 1, 23, 10, 30, 8)),)

pairwise_records

我们根据id和datetime对元组进行排序。按时间排序自然会使对排列整齐。例如,如果某物在上午9点打开,它必须在将来的某个时候关闭;时间是自然排序的。最后,我们使用迭代器的“技巧”将结果组合在一起。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58959495

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档