我有一个看起来像这样的字符串列表:
输入:
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
如何最好地解析上述价目表?
答案 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)
旁边的负索引,并对结果列表列表进行进一步处理,以便处理所有那些讨厌的情况使用正则表达式会出现这种情况。
无论哪种方式,我都会尝试抛出更多极端的例子,以确保它正是您所需要的。