【问题标题】:Convert Python 2 sorted list of tuples to Python 3将 Python 2 排序的元组列表转换为 Python 3
【发布时间】:2021-09-12 19:45:42
【问题描述】:

我正在将一些代码从 Python 2 转换为 Python 3。我有一个元组列表,其中每个元组包含一个数字元组和一组数字。这是一个小例子:

l1_python2 = [
    ((8, 6), Set([1, 2, 3, 4, 5, 6, 7, 8, 9])),
    ((8, 7), Set([1, 2, 3, 4, 5, 6, 7, 8, 9])),
    ((0, 3), Set([1, 2, 5, 6, 7, 9])),
    ((0, 4), Set([1, 2, 5, 6, 7, 9])),
    ((0, 5), Set([1, 2, 5, 6, 7, 9])),
    ((0, 6), Set([1, 2, 5, 6, 7, 9])),
    ((0, 7), Set([1, 2, 5, 6, 7, 9])),
    ((0, 8), Set([1, 2, 5, 6, 7, 9])),
    ((1, 0), Set([1, 2, 5, 6, 7, 9])),
    ((8, 8), Set([1, 2, 3, 4, 5, 6, 7, 8, 9])),
    ((5, 3), Set([1, 2, 3, 4, 5, 6, 7, 8, 9])),
    ((5, 4), Set([1, 2, 3, 4, 5, 6, 7, 8, 9])),
    ((5, 5), Set([1, 2, 3, 4, 5, 6, 7, 8, 9])),
    ((5, 6), Set([1, 2, 3, 4, 5, 6, 7, 8, 9])),
]

l1_python3 = [
    ((8, 6), {1, 2, 3, 4, 5, 6, 7, 8, 9}),
    ((8, 7), {1, 2, 3, 4, 5, 6, 7, 8, 9}),
    ((0, 3), {1, 2, 5, 6, 7, 9}),
    ((0, 4), {1, 2, 5, 6, 7, 9}),
    ((0, 5), {1, 2, 5, 6, 7, 9}),
    ((0, 6), {1, 2, 5, 6, 7, 9}),
    ((0, 7), {1, 2, 5, 6, 7, 9}),
    ((0, 8), {1, 2, 5, 6, 7, 9}),
    ((1, 0), {1, 2, 5, 6, 7, 9}),
    ((8, 8), {1, 2, 3, 4, 5, 6, 7, 8, 9}),
    ((5, 3), {1, 2, 3, 4, 5, 6, 7, 8, 9}),
    ((5, 4), {1, 2, 3, 4, 5, 6, 7, 8, 9}),
    ((5, 5), {1, 2, 3, 4, 5, 6, 7, 8, 9}),
    ((5, 6), {1, 2, 3, 4, 5, 6, 7, 8, 9}),
]

在 Python 2 中排序的代码如下:

l1_python2.sort(
    lambda a, b: len(a[1]) > len(b[1])
    and 1
    or len(a[1]) < len(b[1])
    and -1
    or a[0] > b[0]
    and 1
    or a[1] < b[1]
    and -1
    or 0
)

得到的排序列表是:

[
    ((0, 3), Set([1, 2, 5, 6, 7, 9])),
    ((0, 4), Set([1, 2, 5, 6, 7, 9])),
    ((0, 5), Set([1, 2, 5, 6, 7, 9])),
    ((0, 6), Set([1, 2, 5, 6, 7, 9])),
    ((0, 7), Set([1, 2, 5, 6, 7, 9])),
    ((0, 8), Set([1, 2, 5, 6, 7, 9])),
    ((1, 0), Set([1, 2, 5, 6, 7, 9])),
    ((8, 6), Set([1, 2, 3, 4, 5, 6, 7, 8, 9])),
    ((8, 7), Set([1, 2, 3, 4, 5, 6, 7, 8, 9])),
    ((8, 8), Set([1, 2, 3, 4, 5, 6, 7, 8, 9])),
    ((5, 3), Set([1, 2, 3, 4, 5, 6, 7, 8, 9])),
    ((5, 4), Set([1, 2, 3, 4, 5, 6, 7, 8, 9])),
    ((5, 5), Set([1, 2, 3, 4, 5, 6, 7, 8, 9])),
    ((5, 6), Set([1, 2, 3, 4, 5, 6, 7, 8, 9])),
]

我理解(或认为我理解)这是按集合长度和集合比较排序的。我一直在尝试转换为 Python 3,但没有运气。我首先尝试了这个:

l1_python3.sort(
    key=(
        lambda a, b: len(a[1]) > len(b[1])
        and 1
        or len(a[1]) < len(b[1])
        and -1
        or a[0] > b[0]
        and 1
        or a[1] < b[1]
        and -1
        or 0
    )
)

这给出了一个错误,它缺少一个必需的位置参数 b,这是有道理的。然后我尝试了这个:

l1_python3.sort(
key=(
    lambda a: len(a[0][1]) > len(a[1][1])
    and 1
    or len(a[0][1]) < len(a[1][1])
    and -1
    or a[0][1] > a[1][1]
    and 1
    or a[0][1] < a[1][1]
    and -1
    or 0
)

)

但这会返回一个类型错误,即“int”类型的对象没有 len()。我也尝试了其他一些东西,但它们通常根本不排序。谁能帮帮我?

谢谢!

【问题讨论】:

  • @Carcigenicate 他们实际上是这样做的,因为在 Python 中 andor 返回最后一个操作数(或类似的东西),并不总是 True/False。因此它根据其他操作数返回 -1、1 或 0
  • @Holt 我知道短路,但 sort key 参数不接受 1,-1,0 作为返回 afaik。它需要一个布尔值,在这种情况下1-1True 是相同的。它是一个接受有符号数字的比较器,但这是不同的。
  • @Carcigenicate 啊,是的,但是你应该说你说的是 Python 3 版本,因为在 Python 2 版本中,它使用了比较器(我猜)。
  • @Holt 这可能是真的。我对 2 没有足够的经验,可能会解释行为的差异(编辑:2 的 sort 有一个接受替代行为的 cmp 参数)。
  • Python 2 sort() 期望为 cmp 一个接受 2 个值并返回 -101 的函数,具体取决于哪个更大。 Python 3 期望 key() 接受一个值并返回它应该作为排序依据的值的函数。在 bytes.com 上有 Raymond HeItinger 的配方,用于将一种转换为另一种。谷歌python cmp2keyfunctools 模块中有类似的东西。

标签: python python-3.x sorting python-2.x


【解决方案1】:

奇怪的 lambda 实际上是一种令人费解的说法:

  • 1 如果len(a[0][1]) &gt; len(a[1][1])
  • -1 如果len(a[0][1]) &lt; len(a[1][1])
  • 否则
    • 1 如果a[0][1] &gt; a[1][1]
    • -1 如果a[0][1] &lt; a[1][1]
    • 否则0

所以你首先要比较元素的长度,然后是它们的值(如果长度相等),所以你的键需要是这样的:

l1_python3.sort(
  key=lambda a: (len(a[1]), a[1])
)

【讨论】:

  • 谢谢!那做了我想要的。感谢您解释发生了什么。我没有像我想象的那样理解它。
猜你喜欢
  • 2011-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-15
  • 2017-09-11
  • 1970-01-01
相关资源
最近更新 更多