- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有一个相当大的配置文件,由以 分隔的 block 组成
#start <some-name> ... #end <some-name>
是some-name
该 block 必须相同。该 block 可以出现多次,但永远不会包含在其自身内。只有一些其他 block 可能出现在某些 block 中。我对这些包含的 block 不感兴趣,而是对第二层中的 block 感兴趣。
在真实文件中,名称不以blockX
开头。但彼此之间有很大不同。
一个例子:
#start block1
#start block2
/* string but no more name2 or name1 in here */
#end block2
#start block3
/* configuration data */
#end block3
#end block1
这是使用正则表达式进行解析的,并且在没有附加调试器的情况下运行时速度相当快。
2k
2.7MB 文件需要 0.23 秒,简单规则如下:
blocks2 = re.findAll('#start block2\s+(.*?)#end block2', contents)
我尝试用 pyparsing 解析它,但即使没有附加调试器,速度也非常慢,同一文件需要 16 秒。
我的方法是生成一个 pyparsing 代码,该代码将模仿正则表达式的简单解析,因此我现在可以使用一些其他代码,并避免现在必须解析每个 block 。语法相当广泛。
这是我尝试过的
block = [Group(Keyword(x) + SkipTo(Keyword('#end') + Keyword(x)) + Keyword('#end') - x )(x + '*') for x in ['block3', 'block4', 'block5', 'block6', 'block7', 'block8']]
blocks = Keyword('#start') + block
x = OneOrMore(blocks).searchString(contents) # I also tried parseString() but the results were similar.
我做错了什么?我如何优化它以接近正则表达式实现所达到的速度?
编辑:与真实数据相比,上一个示例非常简单,因此我现在创建了一个合适的示例:
/* all comments are C comments */
VERSION 1 0
#start PROJECT project_name "what is it about"
/* why not another comment here too! */
#start SECTION where_the_wild_things_are "explain this section"
/* I need all sections at this level */
/* In the real data there are about 10k of such blocks.
There are around 10 different names (types) of blocks */
#start INTERFACE_SPEC
There can be anything in the section. Not Really but i want to skip anything until the matching (hash)end.
/* can also have comments */
#end INTERFACE_SPEC
#start some_other_section
name 'section name'
#start with_inner_section
number_of_points 3 /* can have comments anywhere */
#end with_inner_section
#end some_other_section /* basically comments can be anywhere */
#start some_other_section
name 'section name'
other_section_attribute X
ref_to_section another_section
#end some_other_section
#start another_section
degrees
#start section_i_do_not_care_about_at_the_moment
ref_to some_other_section
/* of course can have comments */
#end section_i_do_not_care_about_at_the_moment
#end another_section
#end SECTION
#end PROJECT
为此,我必须扩展您最初的建议。我对两个外部 block (项目和部分)进行了硬编码,因为它们必须存在。
在此版本中,时间仍为 ~16 秒:
def test_parse(f):
import pyparsing as pp
import io
comment = pp.cStyleComment
start = pp.Literal("#start")
end = pp.Literal("#end")
ident = pp.Word(pp.alphas + "_", pp.printables)
inner_ident = ident.copy()
inner_start = start + inner_ident
inner_end = end + pp.matchPreviousLiteral(inner_ident)
inner_block = pp.Group(inner_start + pp.SkipTo(inner_end) + inner_end)
version = pp.Literal('VERSION') - pp.Word(pp.nums)('major_version') - pp.Word(pp.nums)('minor_version')
project = pp.Keyword('#start') - pp.Keyword('PROJECT') - pp.Word(pp.alphas + "_", pp.printables)(
'project_name') - pp.dblQuotedString + pp.ZeroOrMore(comment) - \
pp.Keyword('#start') - pp.Keyword('SECTION') - pp.Word(pp.alphas, pp.printables)(
'section_name') - pp.dblQuotedString + pp.ZeroOrMore(comment) - \
pp.OneOrMore(inner_block) + \
pp.Keyword('#end') - pp.Keyword('SECTION') + \
pp.ZeroOrMore(comment) - pp.Keyword('#end') - pp.Keyword('PROJECT')
grammar = pp.ZeroOrMore(comment) - version.ignore(comment) - project.ignore(comment)
with io.open(f) as ff:
return grammar.parseString(ff.read())
编辑:错字,说是 2k,但实际上是 2.7MB 文件。
最佳答案
首先,发布的这段代码对我不起作用:
blocks = Keyword('#start') + block
更改为:
blocks = Keyword('#start') + MatchFirst(block)
至少与您的示例文本相符。
您可以尝试使用 pyparsing 的自适应表达式之一,matchPreviousLiteral
,而不是硬编码所有关键字:
(已编辑)
def grammar():
import pyparsing as pp
comment = pp.cStyleComment
start = pp.Keyword("#start")
end = pp.Keyword('#end')
ident = pp.Word(pp.alphas + "_", pp.printables)
integer = pp.Word(pp.nums)
inner_ident = ident.copy()
inner_start = start + inner_ident
inner_end = end + pp.matchPreviousLiteral(inner_ident)
inner_block = pp.Group(inner_start + pp.SkipTo(inner_end) + inner_end)
VERSION, PROJECT, SECTION = map(pp.Keyword, "VERSION PROJECT SECTION".split())
version = VERSION - pp.Group(integer('major_version') + integer('minor_version'))
project = (start - PROJECT + ident('project_name') + pp.dblQuotedString
+ start + SECTION + ident('section_name') + pp.dblQuotedString
+ pp.OneOrMore(inner_block)('blocks')
+ end + SECTION
+ end + PROJECT)
grammar = version + project
grammar.ignore(comment)
return grammar
只需在语法中最顶层的表达式上调用 ignore()
- 它将向下传播到所有内部表达式。另外,如果您已经调用了 ignore()
,则无需在语法中添加 ZeroOrMore(comment)
。
我在大约 16 秒内解析了 2MB 输入字符串(包含 10,000 个内部 block ),因此 2K 文件只需要大约 1/1000 的时间。
关于python - 提高分隔配置 block 的解析速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38662521/
我正在尝试从下拉列表中创建一个多选复选框,并通过 ; 连接所选结果。 我的代码是这样的: var myobject = { ValueA : 'Text A', ValueB : 'T
我有输入,我需要获取值并用 “|” 符号分隔。 我的输入: 输出我需要的: 00:00|00:00|00:00 我的代码是: (而且它不工作) var timesArray = $('table').
我正在尝试将超过 400 万行的列拆分为 4 个新列,问题是我不知道在哪里查看或我应该使用 Google 搜索哪个术语。 (是的,我已经在 Google 和 Stack 中搜索了一个类似的问题,但只在
我有一个很大的 csv 文件,其中充满了用“|”分隔的数字字符,例如: 432452 | 543634 4122442 | 41256512 64523 | 12416 然后我读入数据如下: fs
我有一个程序可以计算多个数字的阶乘。这些数字在 cmd 中作为参数传递: factorial.exe 3 4 5 这将分别计算 3、4 和 5 的阶乘。该程序的早期版本有一个百分比显示堆栈的完整性。我
这个问题已经有答案了: 奥 git _a (6 个回答) 已关闭 9 年前。 我有一个双数“547.123456” 我只想使用这个 double 作为“547.1”,就像“.”后面只有 1 个数字 我
我有一个程序可以计算多个数字的阶乘。这些数字在 cmd 中作为参数传递: factorial.exe 3 4 5 这将分别计算 3、4 和 5 的阶乘。该程序的早期版本有一个百分比显示堆栈的完整性。我
我有一个 ArrayList,其中包含一个 messageId、一个 -、一个用户名。 示例:E123-sam 我想划分 List 的每个元素,使得 - 之前的部分进入一个 ArrayList ,而之
我目前有一个“日期”列作为 pandas 数据框的索引,其格式为: January February .... Year2 January February ... Year3 (它来自 pdf 表格
我正在尝试对我的 .mdb 数据库进行 ODBC 查询。我正在使用 mdbtools 驱动程序。该代码是使用 Eclipse 用 C 语言编写的。唯一的问题是,当我写例如: "SELECT 'last
我需要知道如何将这两个if else 部分分开。 public static int NextBday(int Bdays, int days){ int daysleft = 0;
我想计算我的员工分开但合并在一起的出勤率 My target output 我的代码 SELECT count(employees_id) as numbers FROM attendance WH
关闭。这个问题需要details or clarity .它目前不接受答案。 想改进这个问题吗? 通过 editing this post 添加细节并澄清问题. 关闭 7 年前。 Improve t
下面是我的代码的一小段摘录,它从 API 添加了一行。总共有很多行。 每一行包含一行数据如 TY8tr,50,34,P,SB, 数据行在数据类型上是一致的。我如何通过 ,'s 拆分数组列表中
我想获取选中的元素并用逗号分隔它们,最后一个元素用“and”分隔 它的显示输出为: 我想删除最后一个元素后面的逗号 (,) 并在它前面添加 'and',例如 Sugar, Milk and Extra
我是 JSON 的新手,但在从已解析的 JSON 对象中提取数据时遇到问题: 我有一个 getstats.php 文件,它回显 mysql 查询的 json 编码结果。以下是 php 文件返回的示例:
我有一个像这样的数字/字符串(我不确定如何将 int 与字符串相互转换) 000000122310200000223340000700012220000011411000000011011271043
标签内的文本
我想尝试一些基本的网络抓取,但遇到了一个问题,因为我习惯了简单的 td-tags,在这种情况下,我有一个网页,其中包含以下预标记和其中的所有文本,这意味着刮掉它有点棘手。 11111111 1111
出于练习目的,我正在开发 TCP 客户端/服务器系统,我想在两者之间发送特定数据。 我已经能够发送字节并让它们显示为字符串。此外,我还可以发送一个特定的字符串(“mb”)并在服务器端弹出一个 Mess
在大量的 unicode 字符中,有一些实际上表示多个字符,例如两个 'f' 字符的 U+FB00 连字 ff。有什么方法可以轻松地将这样的字符转换为多个单个字符?最好是标准 Java API 中可用
我是一名优秀的程序员,十分优秀!