代码之家  ›  专栏  ›  技术社区  ›  sudonym

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

  •  0
  • sudonym  · 技术社区  · 6 年前

    我有一个字符串列表,如下所示:

    输入:

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

    我想把所有东西都拿走,除了。 isdigit() ,和 '.|,' .换句话说,我想在任何数字第一次出现之前用 maxsplit=1 以下内容:

    期望输出:

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

    第一次尝试(两个regex替换) 以下内容:

    # 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
    

    第二次尝试(仍有两个regex替换):

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

    这(当然)导致了与我第一次尝试相同的输出。而且,它也不短,看起来很难看。有更好(更短)的方法吗?

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

    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 回复  |  直到 6 年前
        1
  •  1
  •   koPytok    6 年前

    如果您只需要留下特定的字符,最好让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']
    
        2
  •  1
  •   Andres Salgado    6 年前

    问题

    如果我错了,请纠正我,但本质上你是想删除符号等,只留下任何尾随的数字,对吗?

    我想在任何数字第一次出现之前拆分

    我认为,这是构建您试图解决的regex问题的最简单方法。

    解决方案

    # -*- 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) 并对生成的列表进行进一步的处理,这样您就可以处理使用regex时出现的所有麻烦的边缘情况。

    不管怎样,我都会尝试用更极端的例子来证明这是你需要的。