Python优雅的方式来映射字符串结构

时间:2018-04-25 12:33:21

标签: python regex string string-matching

让我说事先知道字符串

"key1:key2[]:key3[]:key4"应映射到"newKey1[]:newKey2[]:newKey3"

然后给出"key1:key2[2]:key3[3]:key4"

我的方法应该返回"newKey1[2]:newKey2[3]:newKey3"

(方括号内的数字顺序应该保留,如上例所示)

我的解决方案如下:

predefined_mapping = {"key1:key2[]:key3[]:key4": "newKey1[]:newKey2[]:newKey3"}


def transform(parent_key, parent_key_with_index):
    indexes_in_parent_key = re.findall(r'\[(.*?)\]', parent_key_with_index)

    target_list = predefined_mapping[parent_key].split(":")
    t = []
    i = 0
    for elem in target_list:
        try:
            sub_result = re.subn(r'\[(.*?)\]', '[{}]'.format(indexes_in_parent_key[i]), elem)
            if sub_result[1] > 0:
                i += 1
            new_elem = sub_result[0]
        except IndexError as e:
            new_elem = elem
        t.append(new_elem)
    print ":".join(t)


transform("key1:key2[]:key3[]:key4", "key1:key2[2]:key3[3]:key4")

打印newKey1[2]:newKey2[3]:newKey3作为结果。

有人可以建议一个更好,更优雅的解决方案(尤其是正则表达式的使用)?

谢谢!

1 个答案:

答案 0 :(得分:1)

只需在[]上拆分映射结构,然后从实际数据中散布索引,最后将所有内容连接在一起,就可以更优雅地完成它:

import itertools

# split the map immediately on [] so that you don't have to split each time on transform
predefined_mapping = {"key1:key2[]:key3[]:key4": "newKey1[]:newKey2[]:newKey3".split("[]")}

def transform(key, source):
    mapping = predefined_mapping.get(key, None)
    if not mapping:  # no mapping for this key found, return unaltered
        return source
    indexes = re.findall(r'\[.*?\]', source)  # get individual indexes
    return "".join(i for e in itertools.izip_longest(mapping, indexes) for i in e if i)

print(transform("key1:key2[]:key3[]:key4", "key1:key2[2]:key3[3]:key4"))
# newKey1[2]:newKey2[3]:newKey3

注意:在Python 3上使用itertools.zip_longest()代替。

我仍然认为你过度设计了这个问题,并且对整个问题可能有一个更优雅,更不容易出错的方法。我建议退一步看看更大的图景,而不是仅仅因为它似乎解决了这个特殊的解决方案。