1

全部

我找到了一段代码来解析简单的 ARFF 文件,我想将其更改为适合稀疏 ARFF,其数据如下所示:

@data
{0 12,4 37,8 First,20 'Some Thing'} 
{0 12,13 First,28 'Some Thing'}

这是代码:

def ParseFromSimpleARFF(data):
    arffFormat = Forward()
    E = CaselessLiteral("E")
    comment = '%' + restOfLine
    relationToken = Keyword('@RELATION', caseless=True)
    dataToken = Keyword('@DATA', caseless=True)
    attribToken = Keyword('@ATTRIBUTE', caseless=True)
    ident = Word( alphas, alphanums + '_-' ).setName('identifier')
    relation = Suppress(relationToken) \
               + ident.setResultsName('relation')    
    classDomain = Suppress('{') \
                  + Group(delimitedList(ident.setResultsName('domain'))).setResultsName('domains') + Suppress('}')
    attribute = Group(Suppress(attribToken)
                + Word(alphas).setResultsName('attrname')+(Word(alphas)|classDomain).setResultsName('type')).setResultsName('attribute')            
    arithSign = Word("+-",exact=1)
    realNum = Combine( Optional(arithSign) 
              + (Word( nums ) + "." + Optional( Word(nums) )|( "." + Word(nums) )) 
              + Optional( E + Optional(arithSign) + Word(nums) ))

    **#dataList = Group(delimitedList(realNum|ident)).setResultsName('record')
    dataList = Suppress('{') + Group( delimitedList(realNum|ident)).setResultsName('record')  + Suppress('}')**
    arffFormat << ( relation
                   + OneOrMore(attribute).setResultsName('attributes')
                   + dataToken
                   + OneOrMore(dataList).setResultsName('records')).setResultsName('arffdata')

    simpleARFF = arffFormat
    simpleARFF.ignore(comment)
    tokens =  simpleARFF.parseString(data) 
    return tokens

但它不起作用

我想我必须告诉程序识别空白,但我不知道如何

非常感谢

4

1 回答 1

2

不不不!pyparsing 的很大一部分是“出现空白”!除非您对基于缩进的解析或面向行的数据做一些棘手的事情,否则请在解析器定义中保留空格。

您的问题是您定义为 dataList 的内容与您提供的列表不匹配。列表中的每个以逗号分隔的项目都是一对值,它们似乎允许使用数字或带引号的字符串。所以将 dataList 定义为:

dataCell = realNum|ident|quotedString
dataList = Suppress('{') + Group( delimitedList(Group(dataCell + dataCell)))  + Suppress('}')

其他一些位:

  • 没有必要将 arffFormat 转发声明为 Forward()。仅当数据将嵌套在递归结构中时才需要这样做,即包含子数据的数据。您的示例没有,只需在末尾定义 arffFormatarffFormat = (...etc.

  • x.setResultsName('name')已被简单地替换x('name'),真正清理了解析器代码

  • 您定义了一个 realNum(需要小数点),但您的样本中只有整数。我已经不再构建 realNum 类型的表达式,而是使用本地化的正则表达式:realNum = Regex(r"[+-]?\d+(\.\d*)?([Ee][+-]?\d+)?")将为您提供一个接受整数或实数的表达式。这也将允许您删除其他分散注意力的元素,例如 arithSign。

您也可能在结果名称上过分了。我认为这将使您对数据有一个很好的了解,并在最后提供一个非常易于导航的结构:

arffFormat = ( relation
               + OneOrMore(attribute)('attributes')
               + dataToken
               + OneOrMore(dataList)('records'))('arffdata')
于 2011-06-07T15:11:58.063 回答