如何以pythonic方式将元组一分为二

How to divide a tuple into two in pythonic way

我遇到了一个问题:接收一个包含任何类型对象的元组,并将其分成两个元组:第一个,仅包含字符串;第二个,仅包含字符串;第二个,只有数字。

好的。标准算法类似于:

def separate(input_tuple):
    return_tuple = ([],[])
    for value in input_tuple:
        if isinstance(value, str):
            return_tuple[0].append(value)
        if isinstance(value, numbers.Number):
            return_tuple[1].append(value)
    return tuple([tuple(l) for l in return_tuple])

这样,我们只迭代一次

我的问题是:有没有办法以更 pythonic 的方式做到这一点?一条线?

我试过了

( tuple([i for i in input_tuple if isinstance(i,str)]), tuple([i for i in input_tuple if isinstance(i,numbers.Number)]))

但效率较低,因为我们对输入元组进行了两次迭代。

此外,

tuple([ tuple( [i for i in input_tuple if isinstance(i, k)]) for k in ((float ,int,complex), str) ])

有同样的问题,因为我们做了两次迭代。 是否有可能只迭代一次并仍然得到结果,或者因为我正在处理分离成两个元组,这是不可能的?

谢谢!

我想你可以这样做

my_tuple = ([],[])
for x in a_list:
   my_tuple[isinstance(x,basestring)].append(x) 

这会让它更 pythonic 我想......而且仍然很可读。

当然你也可以把它放在一个列表理解中,但不是很好:

[my_tuple[isinstance(x,basestring)].append(x) for x in a_list]

列表理解被抛弃了,它基本上被滥用到 for 循环中。

试试这个:

tuple(list(filter(lambda e: isinstance(e, t), input_tuple)) for t in (str,int))

它不是单行的,它甚至不等同于您最初所做的,但您可以使用列表容器来提供 "mapping" 功能:

>>> from numbers import Number
>>> tup = (1, '2', 3, '4', 5)
>>> di = {}
>>> for x in tup:
...     di.setdefault(Number if isinstance(x, Number) else str if isinstance(x, str) else object, []).append(x)
... 
>>> di[str], di[Number]
(['2', '4'], [1, 3, 5])

正如@PadraicCunningham 在评论中指出的那样,对于 Python 2,您可以使用 basestring 而不是 str 来捕获 Unicode 类型。