Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用'itertools.groupby()'获取以'A'开头的字符串的运行列表?_Python_Itertools - Fatal编程技术网

Python 使用'itertools.groupby()'获取以'A'开头的字符串的运行列表?

Python 使用'itertools.groupby()'获取以'A'开头的字符串的运行列表?,python,itertools,Python,Itertools,(抽象的)问题是:我有一个日志文件 A: 1 A: 2 A: 3 B: 4 B: 5 A: 6 C: 7 D: 8 A: 9 A: 10 A: 11 我想以这样的列表结束: [["1", "2", "3"], ["6"], ["9", "10", "11"]] 文件被分解为以A开头的字符串的“运行”。我知道我可以使用itertools.groupby来解决这个问题,现在我有了这个解决方案(其中f是文件中的行列表) 所以我使用groupby,但是我必须过滤掉那些不是以“A”开头的东西。这没关系

(抽象的)问题是:我有一个日志文件

A: 1
A: 2
A: 3
B: 4
B: 5
A: 6
C: 7
D: 8
A: 9
A: 10
A: 11
我想以这样的列表结束:

[["1", "2", "3"], ["6"], ["9", "10", "11"]]

文件被分解为以
A
开头的字符串的“运行”。我知道我可以使用
itertools.groupby
来解决这个问题,现在我有了这个解决方案(其中
f
是文件中的行列表)

所以我使用groupby,但是我必须过滤掉那些不是以“A”开头的东西。这没关系,而且非常简洁,但是有没有更优雅的方式呢?我喜欢这样一种方式:

  • 不需要两次传球
  • 是否更简洁(和/或)更具可读性

帮助我利用
itertools
的威力

是,筛选出不是以
A
开头,而是使用
groupby()
为每个返回的组生成的键的行。它是
函数的返回值,因此对于那些以
A
开头的行,它将是
True
。我在这里使用
str.partition()
而不是正则表达式:

coalesce = (g for key, g in groupby(f, key=lambda x: x[:1] == "A") if key)
runs = [[res.partition(':')[-1].strip() for res in group] for group in coalesce]
由于
str.startswith()
参数是一个固定宽度的字符串文字,您也可以使用切片
x[:1]
切片第一个字符,并将其与
'A'
进行比较,这将为您提供与
x.startswith('A')
相同的测试

我使用生成器表达式对
groupby()
过滤进行分组;您可以将其内联到一个列表中:

runs = [[res.partition(':')[-1].strip() for res in group]
        for key, group in groupby(f, key=lambda x: x[:1] == "A") if key]
演示:


是,筛选出不是以
A
开头的行,而是为返回的每个组使用
groupby()
生成的键。它是
函数的返回值,因此对于那些以
A
开头的行,它将是
True
。我在这里使用
str.partition()
而不是正则表达式:

coalesce = (g for key, g in groupby(f, key=lambda x: x[:1] == "A") if key)
runs = [[res.partition(':')[-1].strip() for res in group] for group in coalesce]
由于
str.startswith()
参数是一个固定宽度的字符串文字,您也可以使用切片
x[:1]
切片第一个字符,并将其与
'A'
进行比较,这将为您提供与
x.startswith('A')
相同的测试

我使用生成器表达式对
groupby()
过滤进行分组;您可以将其内联到一个列表中:

runs = [[res.partition(':')[-1].strip() for res in group]
        for key, group in groupby(f, key=lambda x: x[:1] == "A") if key]
演示:


在没有itertools的情况下,在一个循环中可能不太像蟒蛇:

lines = '''
A: 1
A: 2
A: 3
B: 4
B: 5
A: 6
C: 7
D: 8
A: 9
A: 10
A: 11
'''

res = []
cont_last = []
for line in lines.splitlines():
    if line.startswith('A: '):
        cont_last.append(line.replace('A: ', ''))
    else:
        if cont_last:
            res.append(cont_last)
        cont_last = []

if cont_last:
    res.append(cont_last)    

print(res)

在没有itertools的情况下,在一个循环中可能不太像蟒蛇:

lines = '''
A: 1
A: 2
A: 3
B: 4
B: 5
A: 6
C: 7
D: 8
A: 9
A: 10
A: 11
'''

res = []
cont_last = []
for line in lines.splitlines():
    if line.startswith('A: '):
        cont_last.append(line.replace('A: ', ''))
    else:
        if cont_last:
            res.append(cont_last)
        cont_last = []

if cont_last:
    res.append(cont_last)    

print(res)

无需itertools,只需一次迭代即可完成整个文件:

 lines = open('logfile.txt','r').readlines()

 out_list = []
 temp_list = []

 for line in lines:

     if line.split(':')[0].strip() == 'A':
          temp_list.append(line.split(':')[1].strip())

     elif temp_list:
          out_list.append(temp_list)
          temp_list = []

 if temp_list:
     out_list.append(temp_list)
     temp_list = []

 print (out_list)

我知道你要的是
itertools
我手头没有,所以我无法调试它。希望这有帮助。

无需itertools,只需一次迭代即可完成整个文件:

 lines = open('logfile.txt','r').readlines()

 out_list = []
 temp_list = []

 for line in lines:

     if line.split(':')[0].strip() == 'A':
          temp_list.append(line.split(':')[1].strip())

     elif temp_list:
          out_list.append(temp_list)
          temp_list = []

 if temp_list:
     out_list.append(temp_list)
     temp_list = []

 print (out_list)

我知道你要的是
itertools
我手头没有,所以我无法调试它。希望这有帮助。

你想要简洁的吗?好的,你明白了

>>> lst = ['A: 1', 'A: 2', 'A: 3', 'B: 4', 'B: 5', 'A: 6', 'C: 7', 'D: 8', 'A: 9', 'A: 10', 'A: 11']
>>> [[x[1] for x in group[1]] for group in itertools.groupby((line.split(': ') for line in lst), key=lambda a:a[0]) if group[0]=='A']
[['1', '2', '3'], ['6'], ['9', '10', '11']]
从内到外分解:

(line.split(': ') for line in lst)
这是一个生成器表达式,它将每个元素拆分为其alpha键和关联的字符串值

for group in itertools.groupby(..., key=lambda a:a[0])
这只是通过在第一步中确定的alpha键对元素进行分组

... if group[0]=='A'
这只是排除了与问题中指定的标准不匹配的任何结果。如果字符串不是单个字符,则还可以使用组[0].startswith('A')

[x[1] for x in group[1]] for ...]
这是一个列表理解,它根据符合早期条件的
groupby
的结果构建一个列表
groupby
返回一个迭代器作为第二个返回值(
group[1]
),因此我们只需将该迭代器转换为具有列表理解的列表
x[0]
是键值,
x[1]
是紧跟其后的字符串

[...]

所需的输出是一个列表,因此列表理解使其成为列表。整个操作只需对输入进行一次传递。

要简洁吗?好的,你明白了

>>> lst = ['A: 1', 'A: 2', 'A: 3', 'B: 4', 'B: 5', 'A: 6', 'C: 7', 'D: 8', 'A: 9', 'A: 10', 'A: 11']
>>> [[x[1] for x in group[1]] for group in itertools.groupby((line.split(': ') for line in lst), key=lambda a:a[0]) if group[0]=='A']
[['1', '2', '3'], ['6'], ['9', '10', '11']]
从内到外分解:

(line.split(': ') for line in lst)
这是一个生成器表达式,它将每个元素拆分为其alpha键和关联的字符串值

for group in itertools.groupby(..., key=lambda a:a[0])
这只是通过在第一步中确定的alpha键对元素进行分组

... if group[0]=='A'
这只是排除了与问题中指定的标准不匹配的任何结果。如果字符串不是单个字符,则还可以使用组[0].startswith('A')

[x[1] for x in group[1]] for ...]
这是一个列表理解,它根据符合早期条件的
groupby
的结果构建一个列表
groupby
返回一个迭代器作为第二个返回值(
group[1]
),因此我们只需将该迭代器转换为具有列表理解的列表
x[0]
是键值,
x[1]
是紧跟其后的字符串

[...]

所需的输出是一个列表,因此列表理解使其成为列表。整个操作只需对输入进行一次传递。

您不必使用
itertools
。我试着写点东西。我想抽象可能太简单了,所有的字符串都是一个字符吗?数字是按1,2,…,N的顺序上升的吗?@RyanHaining:为什么它太慢了?他们希望根据一个简单的测试选出连续的运行。然后不管测试是什么。@MartijnPieters如果数字真的像那样上升,那么大部分字符串都是无关的,你只需要看第一个字符。我还要确保OP查找的是行的内容,而不是行号(我认为它们是)。@RyanHaining:鉴于其余的描述,我认为可以安全地假设行内容,无论它们是什么,都需要分组。使用带编号的行可以更容易地说明这一点。您不必使用
itertools
。我试着写点东西。我想抽象可能太简单了,所有的字符串都是一个字符吗?数字是按1,2,…,N的顺序上升的吗?@RyanHaining:为什么是这样