【问题标题】:Python: Unexpected ordering in listsPython:列表中的意外排序
【发布时间】:2011-03-24 10:10:29
【问题描述】:

我在 Python 中使用列表时遇到了一个奇怪的行为。我已经实现了一个返回整数列表的方法;特别是,这些是图中的循环,每个循环包括三个节点:

simple_cycles = compute_cycles(graph)

返回给我的是这样的:

[[40000,20000,30000],[700,500,600],[600,500,700],..]

现在,我需要 (1) 对列表中的每个列表进行排序,然后,我需要 (2) 从整个列表中删除重复项,并且 (3) 我需要再次对整个列表进行排序。所需的结果可能如下所示:

[[500,600,700],[20000,30000,40000]]

任务 (1) 是通过在通过 compute_cycles 返回它们之前对内部列表进行排序来实现的。任务(2)和(3)通过执行以下行获得:

cycles = dict((x[0], x) for x in simple_cycles).values()

这适用于处理的第一个图。下面的每个图表都失败了,因为内部列表中的排序有时是错误的。我尝试了最后一行源代码两次,第二个结果出乎意料。例如,我在第二次运行中得到了 x:

[29837921, 27629939, 27646591]

而不是

[27629939, 27646591, 29837921]

这导致选择 29837921 作为字典中的键而不是 27629939。因此,使用 sorted(x) 的初始排序似乎已经是错误的。但是为什么呢?

我试图在我的程序之外重现这种行为,但我做不到。在我的应用程序中,我正在解析这样的 XML 文档:

detector = MyParser()
handler = MyHandler()
handler.subscribe(detector.update)
detector.parse(filename, handler)

..

def parse(self, infile, handler):
  parser = etree.XMLParser(target=handler)
  etree.parse(infile, parser)

执行时,例如,

detector = MyParser()
handler = MyHandler()
handler.subscribe(detector.update)
detector.parse(filename, handler)
detector.parse(filename, handler)

那么第二次运行的顺序就出乎意料了。

我知道,我的源代码示例不适合自己复制,但可能我在处理列表时遗漏了一些基本的 Python 内容。

更新

这里是列表的创建:

from networkx import dfs_successors

def compute_cycles(graph):
  cycles = []
  for node in graph.nodes():
    a = graph.successors(node);
    for a_node in a:
      b = graph.successors(a_node)
      for next_node in b:
        c = graph.successors(next_node);
        if len(c) > 1:
          if c[0] == node:
            cycles.append(sorted([node, a_node, next_node]))
          elif c[1] == node:
            cycles.append(sorted([node, a_node, next_node]))
        else:
          if c == node:
            cycles.append(sorted([node, a_node, next_node]))
        #fi
      #rof
    #rof
  #rof
  return cycles

更新

如果犯了一个大错误:我已经覆盖了我在图中使用的 Node 对象的 __repr__ 函数,以便它返回一个整数。也许,排序失败是因为我处理的是真实对象而不是整数。我以这种方式更改了对sort 函数的调用:

cycles.append(sorted([node, a_node, next_node], key=lambda revision: revision.rev.revid))

我将不得不看看这是否会有所作为。节点类定义如下:

class Node(object):
  def __init__(self, revision, revision_hash):
    self.rev = revision
    self.revhash = revision_hash

  def __repr__(self):
    return repr((self.rev.revid))

【问题讨论】:

  • 没有机会看到错误的代码,你将不得不希望有一个具有心理调试技能的人出现。
  • 您还没有向我们展示对列表进行排序的代码。如果您得到未排序的列表,则问题一定存在。
  • 您是否依赖dict 进行排序?它对事物进行伪随机排序。
  • @Marcelo 我只依靠dict 来删除重复项。

标签: python list no-duplicates


【解决方案1】:

我不明白你为什么使用dict

print sorted(set(tuple(sorted(x)) for x in L))

【讨论】:

  • 他似乎只使用每个三元组的第一个元素作为键,所以需要dict
  • @interjay 他使用第一个元素作为键作为排序的手段,这不起作用,因为字典不保证排序。
【解决方案2】:

字典不一定保持顺序。他们被允许改变它。把它放在解释器中:{'a': 1, 'b': 2, 'c': 3}。我得到了{'a': 1, 'c': 3, 'b': 2}

【讨论】:

  • 我忘了说我对字典不感兴趣,只对值感兴趣。因此,我最终执行了cycles.sort()。
【解决方案3】:

我的问题终于解决了。因为我将对象放入列表而不是简单的Integers,所以我不得不使用sort 方法,如下所示:

sorted([node, a_node, next_node], key=lambda revision: revision.rev.revid))

在这里,我正在访问包含Integer 的成员变量,它已经由__str__ 返回。但是,排序时的隐式转换并不稳定。

【讨论】:

    最近更新 更多