Python正则表达式,用于在字符串中查找和替换

2024-05-04 13:35:48 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试将大文本数据加载到numpy数组。Numpy的loadtxt和genfromtxt对as不起作用

  • 首先,我需要删除以分隔符['#','!','C']开头的注释行
  • 第二,数据中有一个重复模式,其形式为n*value,其中n是重复的整数,value是浮点数据。在

因此,我尝试使用readlines()读取文本文件,然后使用Numpy的loadtxt将数据转换为Numpy数组。在

对于读取和替换,我尝试使用正则表达式(re模块),但无法使其正常工作。但是下面的Python代码正在工作。我的问题是什么是最有效率和Python式的方式来做这件事?在

如果是RegEx,那么在readlines()list对象中执行以下查找和替换的正确RegEx代码是什么:

lines = ['1 2 3*2.5 3 6 1*.3 8 \n', '! comment here\n', '1*1 2.0 2*2.1 3 6 0 8 \n']
for l, line in enumerate(lines):
    if line.strip() == '' or line.strip()[0] in ['#','!','C']:
        del lines[l]        
for l, line in enumerate(lines):
    repls = [word  for word in line.strip().split() if word.find('*')>=0]
    print repls
    for repl in repls:
        print repl
        line = line.replace(repl, ' '.join([repl.split('*')[1] for n in xrange(int(repl.split('*')[0]))]))
    lines[l] = line
print lines

输出如下:

^{pr2}$

编辑:

根据评论,我编辑了如下Python代码:

    in_lines = ['1 2 3*2.5 3 6 1*.3 8 \n', '! comment here\n', '1*1 2.0 2*2.1 3 6 0 8 \n']
    lines = []
    for line in in_lines:
        if line.strip() == '' or line.strip()[0] in ['#','!','C']:
            continue        
        else:
            repls = [word  for word in line.strip().split() if word.find('*')>=0]
            for repl in repls:
                line = line.replace(repl, ' '.join([float(repl.split('*')[1]) for n in xrange(int(repl.split('*')[0]))]))
            lines.append(line)
    print lines

Tags: 数据代码innumpyforifline数组
1条回答
网友
1楼 · 发布于 2024-05-04 13:35:48

Python道

使用python令人敬畏的功能特性和列表理解来代替:

#!/usr/bin/env python

lines = ['1 2 3*2.5 3 6 1*.3 8 \n', '! comment here\n', '1*1 2.0 2*2.1 3 6 0 8 \n']

#filter out comments
lines = [line for line in lines if  line.strip() != '' and line.strip()[0] not in ['#','!','C']]

#turns lines into lists of tokens
lines = [[word for word in line.strip().split()] for line in lines]

# turns a list of strings into a number generator, parsing '*' properly
def generate_numbers(tokens):
  for token in tokens:
    if '*' in token:
      n,m = token.split("*")
      for i in range(int(n)):
        yield float(m)
    else:
      yield float(token)

# use the generator to clean up the lines
lines = [list(generate_numbers(tokens)) for tokens in lines]

print lines

输出:

^{pr2}$

又快又小的Python道

此解决方案使用生成器而不是列表,这样您就不必在内存中加载整个文件。注意两个习语的用法:

  1. with open("name") as file

    这将在退出块后清理文件句柄。

  2. for line in file

    这将使用生成器迭代文件中的行,而无需在内存中加载整个文件。

这给了我们:

#!/usr/bin/env python

# turns a list of strings into a number generator, parsing '*' properly
def generate_numbers(tokens):
  for token in tokens:
    if '*' in token:
      n,m = token.split("*")
      for i in range(int(n)):
        yield float(m)
    else:
      yield float(token)

# Pull this out to make the code more readable
def not_comment(line):
  return line.strip() != '' and line.strip()[0] not in ['#','!','C']

with open("try.dat") as file:
  lines = ( 
    list(generate_numbers((word for word in line.strip().split()))) 
    for line in file if not_comment(line)
  ) # lines is a lazy generator

  for line in lines:
    print line

输出:

➤ ./try.py 
[1.0, 2.0, 2.5, 2.5, 2.5, 3.0, 6.0, 0.3, 8.0]
[1.0, 2.0, 2.1, 2.1, 3.0, 6.0, 0.0, 8.0]

相关问题 更多 >