从列表中删除元组内的空字符串

5

现在我有三个列表是通过RE findall函数生成的,我正在尝试从列表中删除一些空字符串,并在此过程中将数字转换为整数:

得到:[('', '', '1', '1')]

期望:[(1, 1)]

得到:[('', '', '20', '500'), ('21', '失败', '', '')]

期望:[(20, 500), (21, '失败')]

得到:[('3', '失败', '', ''), ('', '', '48', '23'), ('', '', '96', '0')]

期望:[(3, '失败'), (48, 23), (96, 0)]

有什么想法吗?


3
你使用的是哪个正则表达式?为什么不使用一个一开始就不匹配空字符串的正则表达式,而是在之后进行过滤呢? - Tim Pietzcker
我尽力了...但我无法写出不同的正则表达式... - user3238319
1
也许我们可以帮你解决这个问题? - Tim Pietzcker
mission_report('是的,任务3失败了。突袭48已完成:发现目标23个。任务96已完成,发现目标0个') 应该返回 [(3,'失败'), (48, 23), (96, 0)])。我为此编写的正则表达式是:match=re.findall(r'(?:raid|mission) (\d+) (failed)|(\d+) (?:was )?accomplished.*?found: (\d+)', s, re.IGNORECASE) - user3238319
啊,好的,所以总会有两个空的反向引用。我明白了。那么我们就按照你的方式来做吧...等一下。 - Tim Pietzcker
2个回答

8
一个带有元组构造器的嵌套列表推导式:
>>> lst = [('', '', '20', '500'), ('21', 'failed', '', '')]
>>> [(tuple(int(x) if x.isdigit() else x for x in _ if x)) for _ in lst]
[(20, 500), (21, 'failed')]

对于列表lst中的每个元组(_),使用生成器表达式构造一个tuple。仅使用元组构造函数如下:
tuple(int(x) if x.isdigit() else x for x in _ if x)

这段代码看起来很复杂,但我会逐一解释。对于元组_(也是lst中的一个元组)中的每个字符串x,构建一个元组。if x用于检查该字符串是否为空。(如果字符串x为空,则x为false。)if x,生成器表达式将根据x是否为字符串类型的数字,在xint(x)之间产生结果。(试图将非数字字符串转换为整数将导致异常。)

对于lst中的每个元组_,生成器将创建一个新的、相同的元组,除了滤掉空的、false的字符串,并将任何数字字符串转换为int类型的数值。

上述代码等同于:

new_lst = []

for _ in lst: # For each tuple in lst
    for x in _: # For each string in tuple
        temp_tuple = ()
        if x: # Only add to tuple if string is not empty
            if x.isdigit(): # If x is a digit in string form
                temp_tuple += (int(x),) # Convert to int
            else:
                temp_tuple += (x,) # Keep string
    new_lst.append(temp_tuple)

你们能解释一下吗? - user3238319
它返回 [(500,), ()] - user3238319
@user3238319 您将不得不使用确切的输入和输出编辑您的代码。我刚刚在文件开头再次运行了我的代码,对我来说完美地运行了。 - jayelm

5
这样如何:
def sanitize(t):                                
    for i in t:
        try:
            yield int(i)
        except ValueError:
            yield i

inputs = [('3', 'failed', '', ''), ('', '', '48', '23'), ('', '', '96', '0')]
map(tuple, map(sanitize, [filter(None, i) for i in inputs]))

提供以下输出结果:
[(3, 'failed'), (48, 23), (96, 0)]

filter是一个函数,它可以操作一个序列并返回仅为“真值”的元素。空字符串为假值。Map是另一个函数,它接受一个序列并将该序列中的每个元素运行通过给定的函数。在这种情况下,函数sanitize将字符串转换为int(如果可能),否则只返回字符串。

我们在sanitize函数中使用yield而不是return,作为一种简单的方法来向下一个map函数返回另一个序列。或者我们可以在函数内部构建列表并返回它。


1
我在提交之前在shell中进行了测试,所以它是有效的。你需要发布你的实际代码,我才能告诉你哪里出了问题。尝试剥离层并找出哪个不起作用。调试!使用Python控制台进行此类操作。 - aychedee
1
刚刚再次仔细检查了一下,将那段代码复制到终端并运行。运行正常。如果您愿意,我可以重新格式化它以不显示输出。 - aychedee
这是返回映射对象。我猜这可能与Python版本有关。 - MehmedB
没错,这是Python 2,如果你加上 list 将会得到指定的输出。 - aychedee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接