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

在分隔符之间提取具有一定长度的整数

  •  0
  • jezrael  · 技术社区  · 5 年前

    给出一个字符串列表,如:

    L = ['1759@1@83@0#1362@0.2600@25.7400@2.8600#1094@1@129.6@14.4', 
         '1356@0.4950@26.7300@2.9700', 
         '1354@1.78@35.244@3.916#1101@2@40@0#1108@2@30@0',
         '1430@1@19.35@2.15#1431@3@245.62@60.29#1074@12@385.2@58.8#1109',
         '1809@8@75.34@292.66#1816@4@24.56@95.44#1076@47@510.89@1110.61']
    

    我需要在分隔符之间提取所有长度为4的整数 # @ ,并提取第一个和最后一个整数。没有浮动。

    我的解决方案有点过于复杂-用空格替换然后应用 this 解决方案:

    pat = r'(?<!\S)\d{4}(?!\S)'
    out = [re.findall(pat, re.sub('[#@]', ' ', x)) for x in L]
    print (out)
    """
    [['1759', '1362', '1094'], 
     ['1356'], 
     ['1354', '1101', '1108'], 
     ['1430', '1431', '1074', '1109'], 
     ['1809', '1816', '1076']]
    """
    

    是否可以将regex更改为不使用 re.sub

    2 回复  |  直到 5 年前
        1
  •  6
  •   revo shanwije    5 年前

    要允许没有前导或尾随分隔符的第一次和最后一次出现,可以使用负环视框:

    (?<![^#])\d{4}(?![^@])
    

    (?<![^#]) 是一个 近的 同义词 (?:^|#) . 这同样适用于负面展望。

    看现场直播 demo here

        2
  •  3
  •   Rohit Mehrotra    5 年前

    有趣的问题!

    这一点可以很容易地通过“向前看”和“向后看”的概念来解决。

    输入

    pattern = "(?<!\.)(?<=[#@])\d{4}|(?<!\.)\d{4}(?=[@#])"
    out = [re.findall(pattern, x) for x in L]
    print (out)
    

    [['1759', '1362', '1094', '1234'],
     ['1356'],
     ['1354', '1101', '1108'],
     ['1430', '1431', '1074', '1109'],
     ['1809', '1816', '1076', '1110']]
    

    解释

    以上 图案 是由一个 (或操作员)。

    pattern_1 = "(?<!\.)(?<=[#@])\d{4}"
    \d{4}     --- Extract exactly 4 digits
    (?<!\.)   --- The 4 digits must not be preceded by a period(.) NEGATIVE LOOKBEHIND
    (?<=[#@]) --- The 4 digits must be preceded by a hashtag(#) or at(@) POSITIVE LOOKBEHIND
    
    pattern_2 = "(?<!\.)\d{4}(?=[@#])"
    \d{4}     --- Extract exactly 4 digits
    (?<!\.)   --- The 4 digits must not be preceded by a period(.) NEGATIVE LOOKBEHIND
    (?=[@#]   --- The 4 digits must be followed by a hashtag(#) or at(@) POSITIVE LOOKAHEAD
    

    为了更好地理解这些概念, click here

        3
  •  2
  •   Arkistarvh Kltzuonstev    5 年前

    # 或结束 @ 也是:

    [[n for o in p for n in o] for p in [[[m for m in k.split("@") if m.isdigit() and str(int(m))==m and len(m) ==4] for k in j.split("#")] for j in L]]
    

    输出 :

    [['1759', '1362', '1094'], ['1356'], ['1354', '1101', '1108'], ['1430', '1431', '1074', '1109'], ['1809', '1816', '1076']]