使用 python 将字符串转换为字典的有用方法

Useful way to convert string to dictionary using python

我有以下 string 作为输入:

'name SP2, status Online, size 4764771 MB, free 2576353 MB, path /dev/sde, log 210 MB, port 5660, guid 7478a0141b7b9b0d005b30b0e60f3c4d, clusterUuid -8650609094877646407--116798096584060989, disks /dev/sde /dev/sdf /dev/sdg, dare 0'

我编写了使用 python:

将其转换为 dictionary 的函数
def str_2_json(string):
    str_arr = string.split(',')
    #str_arr{0} = name SP2
    #str_arr{1} = status Online
    json_data = {}
    for i in str_arr:
        #remove whitespaces
        stripped_str = " ".join(i.split())  # i.strip()
        subarray = stripped_str.split(' ')
        #subarray{0}=name
        #subarray{1}=SP2
        key = subarray[0] #key: 'name'
        value = subarray[1] #value: 'SP2'
        json_data[key] = value
        #{dict 0}='name': SP2'
        #{dict 1}='status': online'
    return json_data

returndictionary 变成 json (它有 jsonfiy)。

有没有更好的simple/elegant方法?

import json

json_data = json.loads(string)

你的方法很好,除了一些奇怪的事情:

  • 你没有创建 JSON 任何东西,所以为了避免混淆我建议你不要命名你返回的字典 json_data 或你的函数 str_2_json。 JSON,或JavaScript Object Notation 就是——一种将对象表示为文本的标准。对象本身与 JSON.
  • 无关
  • 您可以使用 i.strip() 而不是加入拆分后的字符串(不确定您为什么这样做,因为您注释掉了 i.strip()
  • 您的某些值包含多个 space(例如 "size 4764771 MB""disks /dev/sde /dev/sdf /dev/sdg")。根据您的代码,您将在此类字符串中的第二个 space 之后结束所有内容。为避免这种情况,请执行 stripped_str.split(' ', 1) 以限制拆分字符串的次数。

除此之外,您可以使用 dict() 构造函数和生成器表达式在一行中创建字典:

def str_2_dict(string):
    data = dict(item.strip().split(' ', 1) for item in string.split(','))
    return data

print(str_2_dict('name SP2, status Online, size 4764771 MB, free 2576353 MB, path /dev/sde, log 210 MB, port 5660, guid 7478a0141b7b9b0d005b30b0e60f3c4d, clusterUuid -8650609094877646407--116798096584060989, disks /dev/sde /dev/sdf /dev/sdg, dare 0'))

输出:

{
 'name': 'SP2',
 'status': 'Online',
 'size': '4764771 MB',
 'free': '2576353 MB',
 'path': '/dev/sde',
 'log': '210 MB',
 'port': '5660',
 'guid': '7478a0141b7b9b0d005b30b0e60f3c4d',
 'clusterUuid': '-8650609094877646407--116798096584060989',
 'disks': '/dev/sde /dev/sdf /dev/sdg',
 'dare': '0'
}

这可能与写出完整循环相同(实际上,就效率/时间而言):

def str_2_dict(string):
    data = dict()
    for item in string.split(','):
        key, value = item.strip().split(' ', 1) 
        data[key] = value
    return data

假设这些字段不能包含内部逗号,您可以使用 re.split 来拆分和删除周围的空格。看起来您有不同类型的字段,应该以不同的方式处理。我添加了一个基于字段名称的模式处理程序猜测,它可以用作根据需要转换各种字段的模板。

并且如其他地方所述,没有 json 所以不要使用该名称。

import re

test = 'name SP2, status Online, size 4764771 MB, free 2576353 MB, path /dev/sde, log 210 MB, port 5660, guid 7478a0141b7b9b0d005b30b0e60f3c4d, clusterUuid -8650609094877646407--116798096584060989, disks /dev/sde /dev/sdf /dev/sdg, dare 0'

def decode_data(string):
    str_arr = re.split(r"\s*,\s*", string)
    data = {}
    for entry in str_arr:
        values = re.split(r"\s+", entry)
        key = values.pop(0)
        # schema processing
        if key in ("disks"): # multivalue keys
            data[key] = values
        elif key in ("size", "free"): # convert to int bytes on 2nd value
            multiplier = {"MB":10**6, "MiB":2**20} # todo: expand as needed
            data[key] = int(values[0]) * multiplier[values[1]]
        else:
            data[key] = " ".join(values)
    return data

decoded = decode_data(test)
for kv in sorted(decoded.items()):
    print(kv)

您可以使用正则表达式

import re

def parseString(s):
    dict(re.findall('(?:(\S+) ([^,]+)(?:, )?)', s))

sample = "name SP1, status Offline, size 4764771 MB, free 2406182 MB, path /dev/sdb, log 230 MB, port 5660, guid a48134c00cda2c37005b30b0e40e3ed6, clusterUuid -8650609094877646407--116798096584060989, disks /dev/sdb /dev/sdc /dev/sdd, dare 0"

parseString(sample)

输出:

{'name': 'SP1',
 'status': 'Offline',
 'size': '4764771 MB',
 'free': '2406182 MB',
 'path': '/dev/sdb',
 'log': '230 MB',
 'port': '5660',
 'guid': 'a48134c00cda2c37005b30b0e40e3ed6',
 'clusterUuid': '-8650609094877646407--116798096584060989',
 'disks': '/dev/sdb /dev/sdc /dev/sdd',
 'dare': '0'}