【问题标题】:Compressing function within comprehension在理解范围内压缩函数
【发布时间】:2017-08-29 10:40:52
【问题描述】:

我将l=['1','2','3','rt4','rt5'] 作为输入,并使用以下代码将其转换为l=[1,2,3,'rt4','rt5']

def RepresentsInt(s):
    try: 
        int(s)
        return True
    except ValueError:
        return False

l=['1','2','3','rt4','rt5']
l=[int(l[i]) if RepresentsInt(l[i]) else l[i] for i in range(0,len(l))]  

我可以使用推导改进上述代码吗?

【问题讨论】:

  • 你不能在表达式中使用异常处理(列表推导是一个表达式,只能包含其他表达式),所以你想要的是不可能。您可以将自己限制为仅包含数字的字符串并使用str.isdigit(),但这并不完全相同。

标签: python list list-comprehension


【解决方案1】:

您可以更改您的 RepresentsInt 函数以实际返回整数(如果可能的话),这会更容易:

def RepresentsInt(s):
    try: 
        return int(s)
    except ValueError:
        return s

然后转换列表的代码可以写成(使用for item in l 循环可能比迭代索引更好):

>>> l = ['1','2','3','rt4','rt5']
>>> [RepresentsInt(item) for item in l]
[1, 2, 3, 'rt4', 'rt5']

或者,如果您希望将其作为可重用的模式,您仍然需要一个辅助函数(我在这里选择了类似装饰器的方法),因为您不能在推导中使用 try 和/或 excepts:

def try_to_apply_func(func, exception):
    def newfunc(value):
        try:
            return func(value)
        except exception:
            return value
    return newfunc

>>> to_int_if_possible = try_to_apply_func(int, ValueError)
>>> [to_int_if_possible(item) for item in l]  
[1, 2, 3, 'rt4', 'rt5']

>>> to_float_if_possible = try_to_apply_func(float, ValueError)
>>> [to_float_if_possible(item) for item in l]  
[1.0, 2.0, 3.0, 'rt4', 'rt5']

【讨论】:

    【解决方案2】:

    真的不清楚你想要什么,但可能是这样的:

    >>> l=['1','2','3','rt4','rt5']
    >>> l=[int(i) if i.isdigit() else i for i in l]
    >>> l
    [1, 2, 3, 'rt4', 'rt5']
    

    【讨论】:

      【解决方案3】:

      您可以使用以下代码来获得您想要的结果。

      l = ['1','2','3','rt4','rt5']
      l = [int(each) if each.isdigit() else each for each in l]
      print l
      

      【讨论】:

        【解决方案4】:

        我不相信(尽管我最终可能是错的)有一种更干净、更整洁的方法来实现这一点。一种解决方案是创建一个整数解析 lambda 表达式,如下所示,但我认为您当前的解决方案更简洁、更健壮。

        >>> l = ['1','2','3','rt4','rt5']
        >>> l = list(map(lambda s : (s.isdigit() or (s[0] == '-' and s[1:].isdigit())) and int(s) or s, l))
        >>> l
        [1, 2, 3, 'rt4', 'rt5']
        

        这不会正确捕获诸如'1.0'' 1' 之类的字符串,但它应该可以在两行中执行您想要的操作。

        【讨论】:

        • 你为什么要做list(map(lambda s :而不是列表理解?此外,您的代码不起作用,您缺少)
        • 糟糕,我的错。此外,我已经以某种方式非常普遍地使用map( 语法,并且只是在没有真正考虑的情况下将其应用在这里。西红柿,我猜是西红柿。
        • 除了你的西红柿又长又慢:-)
        • 是的。例如timeit('[x for x in a]', 'a = [0] * 100') 需要大约 2.5 秒,timeit('list(map(lambda x: x, a))', 'a = [0] * 100') 需要大约 7.9 秒。下半场有更多想法here(虽然这里是map+lambda vs generator 表达式)。
        • 仅地图是另一回事。通常不好的是 map + lambda 组合(尤其是如果您甚至需要在它周围使用 list(...) 时)。如果你已经有一个函数,那么映射它是好的,例如,map(int, mystrings)。而在 Python 2 中,map 接受 None 作为函数,并且只要它的 longest 给定可迭代,它就会映射,如果没有 map,这两者都需要更多代码。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多