【问题标题】:Python programmatically parse complex stringPython以编程方式解析复杂字符串
【发布时间】:2020-08-06 22:54:23
【问题描述】:

我不确定这是否可以通过编程方式完成。我已经尝试过在 SO 上找到的各种示例,但专家可能会一看并很快说“停止浪费你的时间”。

Example 2

  • 使用 Python
  • df 包含:21000 行 × 26 列
  • 1 列包含“简短描述”,如下面的两个示例所示,但有许多不同的数据集。
  • 理想情况下,蓝色项目(链接图像)将成为列名,而白色数据将在行中。如果 2100 项中的任何一项具有指定列的值,它将正确填充。
  • 但是,如果我只能选择一个 df 元素并将其解析为两列(左列蓝色内容,右列白色内容),这是可以接受的。

解析:

"Connection=带连接器的电缆,M12x1-Male,4 针,0.30 m,版本=背景灯,尺寸=43 x 9.5 x 64.5 mm,额定工作电压 Ue DC=24 V,最大电流消耗=208 mA, 操作模式=正常, 材料=铝阳极氧化, 黑色玻璃 PMMA, 照明面积=25 x 25 mm, 光源类型=LED 红灯, 波长=617 nm, 照度 (0.1 m)=350 Lux, 光束角=40 ° x 40 °,环境温度=-10...55 °C,认证/符合性=CE;EAC;WEEE,IP 等级=IP54"

产品组=HF (13.56 MHz),产品名称=WLAN,尺寸=100 x 51 x 265 mm,天线类型=棒,支持的数据载体类型=DIN ISO 14443; DIN ISO 15693,显示器=TFT 触摸屏显示器(彩色)480x640 VGA 分辨率,键盘=52 键,字母数字,工作电压 Ub=3.7 V DC 电池组,存储温度=-40...60 °C,环境温度=- 10...50 °C,IP 等级=IP65,认证/符合性=CE; WEEE

或...

Example 1

Excel file with additional "short descriptions"

【问题讨论】:

  • 如果你能想出一个明确的算法来解析数据,那么你很可能会编写一个 Python 程序来做同样的事情。
  • 也许我的帖子措辞不佳;在尝试了几种“明确的算法”之后,尽管我是新手,但我没有成功。一个模式是否会在 SO 上跳出训练有素的眼睛?我感谢@das-g 试一试……它更接近了。

标签: python parsing split


【解决方案1】:

有点老套的解决方案:通过跟踪和错误操作字符串

观察:描述-值对由, 分隔。

所以让我们尝试在这些分隔符处拆分字符串:

line = "Connection=Cable with connector, M12x1-Male, 4-pin, 0.30
 m, Version=Background light, Dimension=43 x 9.5 x 64.5 mm, Rated operating volt
age Ue DC=24 V, Current draw max.=208 mA, Operating mode=Normal, Material=Alumin
um anodized, black Glass PMMA, Illumination area=25 x 25 mm, Light type=LED Red 
light, Wave length=617 nm, Illuminence (0.1 m)=350 Lux, Beam angle=40 ° x 40 °, 
Ambient temperature=-10...55 °C, Approval/Conformity=CE; EAC; WEEE, IP rating=IP
54"

line.split(', ')

是否有逗号 (,) 后面没有空格?让我们检查一下拆分结果是否仍然包含逗号:

>>> any(',' in part for part in line.split(', '))
False

好的。

观察:描述和值用=分隔。

让我们检查我们识别的所有部分是否包含=

>>> all('=' in x for x in line.split(', '))
False

嗯。发生了什么?我们来看看完整的结果:

>>> line.split(', ')
['Connection=Cable with connector',
 'M12x1-Male',
 '4-pin',
 '0.30 m',
 'Version=Background light',
 'Dimension=43 x 9.5 x 64.5 mm',
 'Rated operating voltage Ue DC=24 V',
 'Current draw max.=208 mA',
 'Operating mode=Normal',
 'Material=Aluminum anodized',
 'black Glass PMMA',
 'Illumination area=25 x 25 mm',
 'Light type=LED Red light',
 'Wave length=617 nm',
 'Illuminence (0.1 m)=350 Lux',
 'Beam angle=40 ° x 40 °',
 'Ambient temperature=-10...55 °C',
 'Approval/Conformity=CE; EAC; WEEE',
 'IP rating=IP54']

啊哈:好像有些值包含,

  • Cable with connector, M12x1-Male, 4-pin, 0.30 m
  • Aluminum anodized, black Glass PMMA

这些也被拆分了。

让我们简单地重新加入这些:

fake_parts = line.split(', ')
real_parts = []

for part in fake_parts:
    if '=' in part:
        real_parts.append(part)
    else:
        real_parts[-1] += f', {part}'

看起来怎么样?

>>> real_parts
['Connection=Cable with connector, M12x1-Male, 4-pin, 0.30 m',
 'Version=Background light',
 'Dimension=43 x 9.5 x 64.5 mm',
 'Rated operating voltage Ue DC=24 V',
 'Current draw max.=208 mA',
 'Operating mode=Normal',
 'Material=Aluminum anodized, black Glass PMMA',
 'Illumination area=25 x 25 mm',
 'Light type=LED Red light',
 'Wave length=617 nm',
 'Illuminence (0.1 m)=350 Lux',
 'Beam angle=40 ° x 40 °',
 'Ambient temperature=-10...55 °C',
 'Approval/Conformity=CE; EAC; WEEE',
 'IP rating=IP54']

>>> all('=' in part for part in real_parts)
True

好多了!

现在是否所有部分都只包含一个=?让我们尝试将它们分开:

>>> all(len(part.split('=')) == 2 for part in real_parts)
True

很好。有了它,我们可以组成一个字典:

>>> from collections import OrderedDict

>>> OrderedDict(part.split('=') for part in real_parts)
OrderedDict([('Connection', 'Cable with connector, M12x1-Male, 4-pin, 0.30 m'),
             ('Version', 'Background light'),
             ('Dimension', '43 x 9.5 x 64.5 mm'),
             ('Rated operating voltage Ue DC', '24 V'),
             ('Current draw max.', '208 mA'),
             ('Operating mode', 'Normal'),
             ('Material', 'Aluminum anodized, black Glass PMMA'),
             ('Illumination area', '25 x 25 mm'),
             ('Light type', 'LED Red light'),
             ('Wave length', '617 nm'),
             ('Illuminence (0.1 m)', '350 Lux'),
             ('Beam angle', '40 ° x 40 °'),
             ('Ambient temperature', '-10...55 °C'),
             ('Approval/Conformity', 'CE; EAC; WEEE'),
             ('IP rating', 'IP54')])

或者干脆

>>> dict(part.split('=') for part in real_parts)
{'Ambient temperature': '-10...55 °C',
 'Approval/Conformity': 'CE; EAC; WEEE',
 'Beam angle': '40 ° x 40 °',
 'Connection': 'Cable with connector, M12x1-Male, 4-pin, 0.30 m',
 'Current draw max.': '208 mA',
 'Dimension': '43 x 9.5 x 64.5 mm',
 'IP rating': 'IP54',
 'Illumination area': '25 x 25 mm',
 'Illuminence (0.1 m)': '350 Lux',
 'Light type': 'LED Red light',
 'Material': 'Aluminum anodized, black Glass PMMA',
 'Operating mode': 'Normal',
 'Rated operating voltage Ue DC': '24 V',
 'Version': 'Background light',
 'Wave length': '617 nm'}

现在这可能是您可以使用的东西。但是,这种方法很脆弱:

  • 如果某些描述还包含, ,怎么办?
  • 如果描述或值包含=,该怎么办?
  • 如果格式包含特定的转义序列怎么办?

正确的解决方案:使用解析器

要根据复杂(或不那么复杂)的规则集正确解释编码为文本的数据,请使用解析器库。参见例如How best to parse a simple grammar? 用于选项。

这需要您指定控制编码的确切规则集(称为“语法”),因此也需要了解这些规则。通过查看编码数据是否可以以及如何得出这些规则,取决于该数据。

【讨论】:

  • 感谢您的帮助;看起来我的长数据集太不可靠了。我发现就像你警告的那样,描述中有一些“,”。不过,我相信您的 cmets 会帮助其他面临同样问题的人。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-20
  • 2012-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多