【问题标题】:How to divide a tuple into two in pythonic way如何以pythonic方式将一个元组分成两个
【发布时间】:2015-07-10 20:01:57
【问题描述】:

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

好的。标准算法类似于:

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])

这样,我们只迭代一次

我的问题是:有没有办法以更蟒蛇的方式来做?单线?

我试过了

( 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) ])

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

谢谢!

【问题讨论】:

  • 不要采用“pythonic 方式”,这是一个没有用处的陷阱,而且几乎总是将一段相当易读且易于理解的代码简化为 1-line-decoder-ring-需要混乱。您的目标应该是将代码格式化为易于维护和阅读的格式,而不是尽可能少的行。
  • @TymoteuszPaul 我知道这一点。我实际上并没有使用该代码,但在考虑列表理解时我感到有限,而且我最近一直在研究它;堆栈溢出的人总是用他们的答案给我留下深刻印象,所以这就是为什么我想知道这是否可能!不过谢谢你的建议!毕竟,“显式胜于隐式”!
  • 在 Java 中,我们亲切地称之为进程拆分!拆分器ftw。
  • 虽然“pythonic”有点旁观者的眼光,但我认为做两个单独的列表推导是可读的、可维护的并且不会影响算法的复杂性,因此实际上是相当 Pythonic。结果通常会让您在速度方面感到惊讶,因此我建议您计时。
  • 为什么这么多人似乎认为“Pythonic”的意思是“尽可能聪明”或“尽可能短”?在判断 Pythonic 的程度时,可读性可能是最重要的一个品质。如果你让你的代码不那么可读,那么你也让它不那么 Pythonic。是的,关于什么是“可读”的意见不同。但可读性绝对是 Pythonic 理想中的一个目标,而简洁和聪明则不是。

标签: python python-2.7 tuples list-comprehension


【解决方案1】:

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

>>> 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 在 cmets 中指出的那样,对于 Python 2,您可以使用 basestring 而不是 str 来捕获 Unicode 类型。

【讨论】:

  • 一旦你遇到任何非 int 或 str 就会中断
  • @PadraicCunningham 已修复以使其牢不可破。
  • 哇,我猜这是最pythonic的答案。我也永远不会想到这一点!感谢@Shashank的回答
  • @RafaelCardoso,关键函数可以任意复杂......例如,您可以通过将 isinstance 的值映射到数字等来处理多种类型。
  • 已经有了我的 plus 1 但你应该使用 Python 2 的 basestring。
【解决方案2】:

试试这个:

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

【讨论】:

  • 非常聪明....不幸的是它仍在迭代两次 :) 但我认为这是一个很酷的答案 (+1)
  • 真是不错的选择!然而,正如 Joran 所说,它的循环次数是我的代码的两倍!
  • 虽然代码很受欢迎,但它应该始终有一个附带的解释。这不必很长,但在意料之中。
【解决方案3】:

我想你可以做类似的事情

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 循环中。

【讨论】:

  • 你会如何处理他的“任何类型的对象”?您的代码将列表、集合等添加到数字元组中。
  • true 这是一个非常二元的解决方案,其中列表的所有元素都被分类到两个箱中的一个......这满足了我对原始问题陈述的阅读,所以我只想说这个简单的分类字符串和非字符串(可能足够也可能不够)
猜你喜欢
  • 2019-09-03
  • 2010-10-09
  • 2011-03-31
  • 1970-01-01
  • 2019-05-03
  • 2015-11-10
  • 1970-01-01
  • 2021-11-20
  • 2019-04-06
相关资源
最近更新 更多