python中的价格解析-如何在第一次出现任何数字之前将列表中的所有字符串拆分一次?

时间:2018-06-20 04:51:16

标签: python string list-comprehension

我有一个看起来像这样的字符串列表:

输入:

prices_list = ["CNY1234", "$ 4.421,00", "PHP1,000", "€432"]

我想删除。isdigit()'.|,'以外的所有内容。换句话说,我想在maxsplit=1出现任何数字的第一个出现之前进行拆分:

所需的输出:

["1234", "4.421,00", "1,000", "432"]

首次尝试(两次正则表达式替换)

# Step 1: Remove special characters
prices_list = [re.sub(r'[^\x00-\x7F]+',' ', price).encode("utf-8") for price in prices_list]
# Step 2: Remove [A-Aa-z]
prices_list = [re.sub(r'[A-Za-z]','', price).strip() for price in prices_list]

当前输出:

['1234', '$ 4.421,00', '1,000', '432']   # $ still in there

第二次尝试(仍两次替换正则表达式):

prices_list = [''.join(re.split("[A-Za-z]", re.sub(r'[^\x00-\x7F]+','', price).encode("utf-8").strip())) for price in price_list]

(当然)这会导致与我的第一次尝试相同的输出。而且,它并没有缩短很多,而且看起来很丑陋。有更好的(更短的)方法吗?

第三次尝试(列表理解/嵌套for-循环/无正则表达式):

prices_list = [''.join(token) for token in price for price in price_list if token.isdigit() or token == ',|;']

产生的结果:

NameError: name 'price' is not defined

如何最好地解析上述价目表?

2 个答案:

答案 0 :(得分:1)

如果只需要保留特定字符,最好让regex完全执行该操作:

import re

prices_list = ["CNY1234", "$ 4.421,00", "PHP1,000", "€432"]

prices = list()
for it in prices_list:
    pattern = r"[\d.|,]+"
    s = re.search(pattern, it)
    if s:
        prices.append(s.group())

> ['1234', '4.421,00', '1,000', '432']

答案 1 :(得分:1)

问题

如果我错了,请更正我,但是从本质上讲,您正在尝试删除符号等,只保留任何结尾的数字,对吗?

  

我想在任何数字首次出现之前进行分割

我认为,这是框架您要解决的正则表达式问题的最简单方法。

解决方案

# -*- coding: utf-8 -*-
import re

# Match any contiguous non-digit characters
regex = re.compile(r"\D+")

# Input list
prices_list = ["CNY1234", "$ 4.421,00", "PHP1,000", "€432"]

# Regex mapping
desired_output = map(lambda price: regex.split(price, 1)[-1], prices_list)

这给了我['1234', '4.421,00', '1,000', '432']作为输出。

说明

之所以起作用,是因为有lambda和map函数。基本上,map函数接受一个lambda(如果可以的话,是一个可移植的单行函数),并在列表中的每个元素上执行它。负索引采用split方法生成的匹配项列表的最后一个元素

从本质上讲,这是有效的,因为假设您不希望输出中出现任何初始非数字。

注意事项

  • 此代码不仅将.,保留在结果子字符串中,而且将所有字符保留在结果子字符串中。因此,输入字符串"$10e7"将作为'10e7'输出。

  • 如果仅输入数字,而将.,(例如"10.00")作为输入字符串,则将在相应位置获得'00'在输出列表中。

如果这些都不是理想的行为,则必须摆脱regex.split(price, 1)旁边的负索引,并对结果列表列表进行进一步处理,以便处理所有那些讨厌的情况使用正则表达式会出现这种情况。

无论哪种方式,我都会尝试抛出更多极端的例子,以确保它正是您所需要的。