【问题标题】:Python One-Liner: Sorting by multiple, interdepending keysPython One-Liner:按多个相互依赖的键排序
【发布时间】:2015-08-25 23:01:58
【问题描述】:

免责声明:这个问题是关于我的,希望其他人更好地理解 Python。我知道,我的问题可以通过不止一行轻松解决。

假设我有两个函数 f(x), g(x,y),这样我就可以计算元组 ( f(x), g(x,f(x)) ) 作为 x 的函数。 我想通过这两个键对列表 X 进行排序,但是计算 f(x) 很昂贵,所以我只想对每个 x 执行一次。我目前的解决方案是:

X_s = sorted( X , key =  lambda x: (lambda y: ( y , g(x,y) ) )( f(x) ) )

我可以在不使用两个 lambda 函数的情况下达到同样的效果吗?

【问题讨论】:

  • 我已经尝试过多次回答这个问题,但最终还是让自己感到困惑。只用一个 lambda 似乎不可能做你想做的事。 Python 没有任何记忆功能,就像 Haskell 一样,所以你需要一个 lambda 来计算 f,另一个来计算 h(x) = (f(x), g(x, f(x))
  • 这正是我的想法。感谢您的光荣尝试。
  • 你还是应该接受答案
  • @BlueTrin:我会的,但在截止日期前不久这样做并没有错...

标签: python sorting lambda key


【解决方案1】:

没有一个漂亮的单线。但是,对于使用较少 lambda 的模糊单行代码,有很多选项。

例如,可以像这样使用单个 lambda 表达式

X_s = [a, for (b, a) in sorted(zip(map(f, X), X), key=lambda y,x: (y, g(x,y)))]

或者没有任何 lambdas

X_s = [x for (_, _, x) in sorted([(y, g(x,y), x) for (x,y) in zip(X, map(f, X))])]

但这些总是丑陋的。除了玩得开心之外,你应该使用真正的循环来解决这个问题。

【讨论】:

  • 我同意你的,因为你也有一个没有 lambda 的解决方案 :)
【解决方案2】:

我喜欢谜题,所以我试了一下:)我设法在给定的条件下解决了这个问题,但只是以一种非常丑陋的方式:

X_s = sorted(X, key=lambda x: [(f0, g(x, f0)) for f0 in [f(x)]][0])

所以,绝对可以用一个 lambda 函数在一行中做到这一点,但我不得不用列表推导替换第二个 lambda。

【讨论】:

  • 嗯,它与我自己的两个 lambdas 解决方案在丑陋方面竞争,但它是一个候选者。它类似于我在描述中的提示。我想知道为什么它必须那么难看,因为显然避免对 f(x) 进行多次评估并非不可能。这是关于为下一次计算动态存储一个值,但由于 lambdas 不能有超过一行,我想知道是否有更优雅的结构来克服这个问题。
  • @FitzgeraldCreen:优雅的方法是不要向后弯腰在一行中完成。
  • 查看免责声明。
【解决方案3】:

这是我使用生成器的建议(有点冗长,但应该可以解决问题):

from operator import itemgetter

X_s = sorted(((f, g(x,f)) for x,f in ((x,f(x)) for x in X)), key=itemgetter(0,1))

顺便说一句,我意识到这是 2 行,但第一行只是导入一个标准模块以使多个键的排序更具可读性(我更喜欢它而不是 lambda)。

编辑:

请意识到我最初的答案并没有完全给出您要求的输出。应该这样做(尽管更冗长):

X_s = [y[2] for y in sorted(((f,g(x,f),x) for x,f in ((x,f(x)) for x in X)), key=itemgetter(0,1))]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-18
    • 2011-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-26
    相关资源
    最近更新 更多