我收到一个输入字符串,该字符串具有以两种可能的格式表示的值。例如:
#short format
data = '"interval":19'
>>> "interval":19
#extended format
data = '"interval":{"t0":19,"tf":19}'
>>> "interval":{"t0":19,"tf":19}
我想检查是否使用了短格式,以防万一,将其扩展。
考虑到字符串可以由多个值组成,即
data = '"interval":19,"interval2":{"t0":10,"tf":15}'
>>> "interval":19,"interval2":{"t0":10,"tf":15}
我不能只说:
if ":{" not in data:
#then short format is used
我想编写如下代码:
if ":$(a general int/float/double number)" in data:
#extract the number
#replace ":{number}" with the extended format
我知道如何编写替换部分的代码。
我需要实现if
条件的帮助:在我看来,我将其建模为变量子字符串,其中变量部分是其中的数字,而刚性格式是$(值名称)+“:”部分。
"some_value":19
^ ^
rigid format variable part
编辑-为什么不解析它?
我知道字符串是“ JSON友好的”,我可以将其转换为字典,然后轻松地访问值。
确实,我的代码中已经有此解决方案。但是我不喜欢它,因为输入字符串可能是多级的,并且我需要独立于词典级别对生成的词典的叶值进行迭代。后者不是一件容易的事。
所以我想知道是否存在一种直接作用于字符串的方法。
答案 0 :(得分:2)
如果替换t0
,tf
以外的所有键,然后加上数字,则应该可以。
我为您展示了一个有关多级字符串的示例,该示例可能具有更好的形状:
import re
s = '"interval": 19,"t0interval2":{"t0":10,"tf":15},{"deeper": {"other_interval":23}}'
gex = '("(?!(t0|tf)")\w+":)\s*(\d+)'
new_s = re.sub(gex, r'\1 {"t0": \3, "tf": \3}', s)
print(new_s)
>>> print(new_s)
"interval": {"t0": 19, "tf": 19},"t0interval2":{"t0":10,"tf":15},{"deeper": {"other_interval": {"t0": 23, "tf": 23}}}
答案 1 :(得分:1)
您可以使用正则表达式。 ("interval":)(\d+)
将查找字符串'"interval":'
,后跟任意数字。
让我们测试一下
data = '"interval":19,"interval2":{"t0":10,"tf":15},"interval":25'
result = re.sub(r'("interval":)(\d+)', r'xxx', data)
print(result)
# -> xxx,"interval2":{"t0":10,"tf":15},xxx
我们看到我们找到了正确的地方。现在,我们将创建您的目标格式。匹配的组在这里派上用场。在正则表达式("interval":)
中是组1,(\d+)
是组2。
现在,我们使用这些组的内容来创建您想要的结果。
data = '"interval":19,"interval2":{"t0":10,"tf":15},"interval":25'
result = re.sub(r'("interval":)(\d+)', r'\1{"t0":\2,"tf":\2}', data)
print(result)
# -> "interval":{"t0":19,"tf":19},"interval2":{"t0":10,"tf":15},"interval":{"t0":25,"tf":25}
如果涉及浮点值,则必须将(\d+)
更改为([.\d]+)
。
如果不仅需要interval
,而且还需要任何Unicode标准单词字符,则可以使用特殊序列\w
,并且由于它可能是多个字符,因此表达式将为\w+
。
data = '"interval":19,"interval2":{"t0":10,"tf":15},"Monty":25.4'
result = re.sub(r'("\w+":)([.\d]+)', r'\1{"t0":\2,"tf":\2}', data)
print(result)
# -> "interval":{"t0":19,"tf":19},"interval2":{"t0":{"t0":10,"tf":10},"tf":{"t0":15,"tf":15}},"Monty":{"t0":25.4,"tf":25.4}
当!是的,我们找到了"Monty"
,但是现在也找到了第二部分的值。我们必须以某种方式解决此问题。让我们来看看。我们不希望("\w+")
前面有{
,因此将在断言后使用负向查找 :(?<!{)("\w+")
。在数字部分(\d+)
之后,我们不需要}
或其他数字,因此我们在这里使用负超前断言:([.\d]+)(?!})(?!\d)
。 / p>
data = '"interval":19,"interval2":{"t0":10,"tf":15},"Monty":25.4'
result = re.sub(r'(?<!{)("\w+":)([.\d]+)(?!})(?!\d)', r'\1{"t0":\2,"tf":\2}', data)
print(result)
# -> "interval":{"t0":19,"tf":19},"interval2":{"t0":10,"tf":15},"Monty":{"t0":25.4,"tf":25.4}
万岁,行得通!
正则表达式功能强大且有趣,但是如果您开始添加更多约束,则可能变得难以管理。