鉴于任意收集,有没有办法告诉它是否被订购?

时间:2012-05-02 10:36:11

标签: python collections python-2.7

这是我到目前为止所拥有的:

def is_ordered(collection):
    if isinstance(collection, set):
        return False
    if isinstance(collection, list):
        return True
    if isinstance(collection, dict):
        return False

    raise Exception("unknown collection")

有更好的方法吗?

NB:我的意思是命令并且排序。

动机:

我想迭代一个有序的集合。 e.g。

def most_important(priorities):
    for p in priorities:
        print p

在这种情况下,优先级有序的事实很重要。什么样的收藏不是。我想在这里打鸭子。我经常被Pythonistas的类型检查所劝阻。

4 个答案:

答案 0 :(得分:4)

如果集合真的是任意的(意味着它可以是任何类),那么答案必须是

基本上,有两种可能的方法:

  1. 了解可以呈现给您的方法的每个可能的类,以及它是否已订购;
  2. 通过将每个可能的键组合插入其中,并查看是否保留了顺序来自行测试该集合。
  3. 后者显然是不可行的。前者与您已有的一致,除了您必须了解每个派生的类,例如collections.OrderedDict;检查dict是不够的。

    坦率地说,我认为整个is_ordered检查是一堆蠕虫。你为什么要这样做呢?

答案 1 :(得分:1)

更新:从本质上讲,您正在尝试对传递给您的参数进行单元测试。停止这样做,并对您自己的代码进行单元测试。测试您的消费者(确保它适用于有序集合),并对调用它的代码进行单元测试,以确保它获得正确的结果。

在静态类型语言中,您只需将自己局限于特定类型。如果你真的想要复制它,只需指定你接受的唯一类型,并测试它们。如果传递任何其他内容,则引发异常。它不是pythonic,但它可靠地实现了你想做的事情


嗯,你有两种可能的方法:

  1. 任何使用append方法的东西几乎都是有序的;和
  2. 如果它只有一个add方法,你可以尝试添加一个nonce-value,然后遍历该集合以查看nonce是否出现在结尾(或者,可能在一端);你可以尝试添加第二个nonce,再做一次就可以更自信了。
  3. 当然,这不适用于该集合为空,或者存在一个不会在末尾添加的排序函数。

    可能更好的解决方案就是指定您的代码需要有序集合,并且只传递有序集合。

答案 2 :(得分:0)

我认为列举90%的情况与你将得到的一样好(如果使用Python 3,则用str替换basestring)。可能还想考虑如何处理生成器表达式和类似的同类(再次,如果使用Py3,跳过xrangor):

generator = type((i for i in xrange(0)))
enumerator = type(enumerate(range(0)))
xrangor = type(xrange(0))
is_ordered = lambda seq : isinstance(seq,(tuple, list, collections.OrderedDict,
                                          basestring, generator, enumerator, xrangor))

如果您的调用者开始使用itertools,那么您还需要添加islice,imap,groupby返回的itertools类型。但是这些特殊情况的绝对数量确实开始指向code smell

答案 3 :(得分:-1)

如果没有订购列表怎么办,例如[1,3,2]?