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

Python多重拆分条件

  •  1
  • geoJshaun  · 技术社区  · 2 年前

    我有一个表,其中有一个街道编号字段,应该都是数值,但数据集的创建者允许567M或4321.5等无效值来指示公寓号或奶奶单元。我需要将整数放入一个新字段,并将字母值和十进制值放入街道后缀字段。我一直在玩regex和 isalpha() isalnum() :

    # import regex
    import re
    
    # list of values that should be all numbers
    lst = ['1234', '4321.5', '567M']
    
    # create new lists where l1 will be numeric datatypes and l2 will contain suffixes
    # if there is a decimal symbol the string should be split with first value being all numbers
    # and going into l1 and everything after decimal in l2
    l1 = []
    l2 =[]
    
    for i in lst:
        if i.isalnum(): # all characters are numeric and good to go. Maybe need to do int()? 
            l1.append(i)
        elif '.' in i: # a decimal was found and values need to to be split and placed into two different lists
            i.split(".")
            l1.append(i[0])
            l2.append(i[-1])
        else:
            if i.isnumeric() == False: # if a letter is found in a list item everything prior to letter goes to l1 and letter goes to l2
                i = re.split('(\d+)', i)
                l1.append(i[0])
                l2.append(i[-1])
    

    我在运行代码时立即得到了以下信息:

    ['4321', '5']
    

    然后得到了这个 l1 l2 ( l1 是新的数字列表,并且 l2 是字符串后缀列表):

    ['4321', '5']
    l1
    ['1234', '4', '567M']
    l2
    ['5']
    

    我朝着正确的方向走了吗?我希望这会更简单,但数据很不稳定。

    2 回复  |  直到 2 年前
        1
  •  0
  •   bztes    2 年前

    您可以使用正则表达式来进行模式匹配。表达式将由三个部分组成:

    1. 街道编号: [1-9]\d*
    2. 可选的分隔符,例如-: [\.,\- ]*
    3. 后缀(除空格外的任何字符): [^\s]*
    import re
    
    pattern = re.compile(r'(?P<number>[1-9]\d*)[\.,\- ]*(?P<suffix>[^\s]*)')
    
    list = ['1234', '4321.5', '567M', ' 31-a ']
    l1 = []
    l2 = []
    for item in list:
        match = pattern.search(item)
        if match:
            l1.append(int(match.group('number')))
            l2.append(match.group('suffix'))
        
    print(f'l1: {l1}')
    print(f'l2: {l2}')
    

    后果

    l1: [1234, 4321, 567, 31]
    l2: ['', '5', 'M', 'a']
    
        2
  •  0
  •   Blckknght    2 年前

    你的第一个问题是 i.split(".") 本身没有做任何有用的事情,它 退货 一份分片的清单。你没有使用它(看起来你的解释器正在为你打印它),然后你继续索引到原始的、未拆分的字符串中 i = i.split(".") 修复代码的这一部分,但下面我建议一个更好的方法。

    另一个问题是正则表达式分割代码也不起作用。与其尝试修复它,我建议使用完全不同的regex方法,它还将处理您正在查看的其他情况:

    for i in lst:
        match = re.match(r'(\d+)\.?(.*)', i)
        if match is None:
            raise ValueError("invalid address format {i}")
        l1.append(match.group(1))
        l2.append(match.group(2))
    

    这使用正则表达式模式来匹配所需街道编号的两个部分。任何前导数字部分都会被第一个捕获组匹配并放入 l1 ,并且后面的任何其他内容(可选地在小数点之后)都进入 l2 。如果街道编号没有多余的部分,第二部分可能是一个空字符串,但我仍然将其放入 l2 ,当你尝试迭代时,你会很感激 l1 l2 在一起