天天看点

key-value pair列表parser

类似属性文件那样, key1 = value1, key = value2

简练的算法,只区分word字符和分隔字符(空格, tab, 逗号,=等等),不需要处理key和vaue的分隔符(=)。就是parse word,tokenize,分词驱动,分出一个词来做什么操作的问题,就是考虑一点,作为key还是value。用一个key变量记录状态就好了,key是空则当前word是key, key有值,则当前word是value。key和value总是交替出现的。

def parseKVPairs(s):
    wordStart, key, sep, result = -1, '', ' \t=,:', {}
    for i in xrange(len(s)):
        if s[i] not in sep:
            if i == 0 or s[i - 1] in sep: wordStart = i
            if i == len(s) - 1 or s[i + 1] in sep:
                if key == '': key = s[wordStart: i + 1]
                else:
                    result[key] = s[wordStart: i + 1]
                    key = ''
    return result
print parseKVPairs("key = abc, key2 ; xyz ,    key3=kkk")
           

假如允许有些key没有value,那就得处理=或者:了,框架还是分词,多记录一个状态:处在key的范围还是value的范围,inValue == True表示在value的范围,否则在key的范围,初始为False,在key的范围。

def parseKVPairs(s):
    wordStart, key, sep, inValue, result = -1, '', ' \t=,:', False, {}
    for i in xrange(len(s)):
        if s[i] not in sep:
            if i == 0 or s[i - 1] in sep: wordStart = i
            if i == len(s) - 1 or s[i + 1] in sep:
                if not inValue:
                    if key != '': result[key] = ''
                    key = s[wordStart: i + 1]
                else:
                    result[key] = s[wordStart: i + 1]
                    inValue, key = False, ''
        elif s[i] in ':=': inValue = True
    return result
print parseKVPairs("key = abc, key2, key3 = v3")
           

这里逗号,空格,tab完全是一样的,只用于分词。等号(或冒号)除了用于分词,还触发key scope 到 value scope的切换,之后分出一个词fulfill value后,scope切换回key

其实,逗号和空格同作为分隔字符,语义上还有其他差别,一般情况下,逗号的语义更多:前面必须有有效词,后面也必须有词 ,这里没有强制这一层语义。

继续阅读