【问题标题】:Is there a nice pythonic way to make an lvalues permutation?有没有一种很好的 Pythonic 方法来进行左值排列?
【发布时间】:2020-03-30 15:13:40
【问题描述】:

假设您想对一组数据进行非对称转换,但您希望数据在此转换方面是对称的。你会

  1. 对您的数据进行随机排列,
  2. 对排列后的数据进行非对称转换,
  3. 反转排列以将数据放回原位。

问题:在原始数据空间上进行排列以将数据放回原处比构建反向排列要容易得多。


示例:要生成远离背景色的随机前景色,您需要远离三种基本颜色中的一种,并且其他两种颜色都可能是随机的。 假设我的背景颜色是:

import random
background = tuple(random.randint(0, 0xff) for _ in range(3))

让我们随机选择一个组件:

selector = random.choice(((0, 1, 2), (1, 0, 2), (2, 0 ,1)))

然后,我将选择我的第一个组件,远离那个:

far_component = 0xff if background[selector[0]] < 0x80 else 0

然后我将根据我的初始选择创建前景色:

foreground = list(range(3))
foreground[selector[0]] = far_component
foreground[selector[1]] = random.randint(0, 0xff)
foreground[selector[2]] = random.randint(0, 0xff)

在这个简单的例子中,事情是很容易处理的,但是让我们想象一个更复杂的例子,它有更多的维度。它将需要一个循环来管理所有输出分配,如下所示:

variable = len(selector)*None # If ever variable doesn't exist yet.
for i in range(len(selector)):
    variable[selector[i]] = ordered_source_tuple[i]

是否有一种很好的 Pythonic 方式来编写这样一个看起来像变量理解列表的赋值。像这样的东西(这显然行不通,因为左边的部分不是 LValues 的元组):

(variable[i] for i in selector) = ordered_source_tuple

找到反向排列来写这不是简单的操作

variable = ordered_source_tuple(reversed_selector)

【问题讨论】:

  • 这是一个关于 Python 中左值的一般性问题。但是,在这种情况下,您是否可以通过为 每个 前景组件分配随机值,然后用far_component 随机覆盖一个来简化您的代码?
  • 好吧,考虑一下,它可能会破坏这个例子,因为我的观点是可能有更多的维度和不止一个非随机值。但我用另一种方式简化了它。
  • 要明确一点,在您的问题中,selectorordered_source_tuple 的长度是否可以小于原始序列 (variable)?
  • 不,在这种一般情况下,所有文件的大小都相同。我只想反转原始排列,而不必构建反转排列选择器。大致思路是:做一个随机排列——根据特定的计划修改排列后的数据——把修改后的数据放回原来的位置。
  • 我在主要问题中添加了信息以回答您的问题

标签: python list-comprehension permutation lvalue


【解决方案1】:

创建新颜色,然后在分配给foreground之前对其进行置换。

import random
from operator import itemgetter


background = tuple(random.randint(0, 0xff) for _ in range(3))
selector = random.choice(((0, 1, 2), (1, 0, 2), (2, 0 ,1)))
far_component = 0xff if background[selector[0]] < 0x80 else 0

permute = itemgetter(*selector)
components = [far_component, random.randint(), 0xff), random.randint(0, 0xff)]
foreground = permute(components)

【讨论】:

  • 我相信你错过了一个简单的例子,可能更复杂的事情。
【解决方案2】:

这不再是单行了,但是如果你像this answer那样定义一个辅助函数,它就变成了一个:

def inverted_permutation(p):
    inverse = [0] * len(p)
    for i, p in enumerate(p):
        inverse[p] = i
    return inverse

variable = tuple(source[i] for i in inverted_permutation(selector))

当然,这或多或少等同于你的赋值循环,但它隐藏在一个有点通用的函数中。

【讨论】:

  • 嗯,这和我的循环差不多,但你把它放在一个函数中......
【解决方案3】:

这可能是作弊,但是字典怎么样:

variable = dict(zip(selector, ordered_source_tuple))

如果你想把它变回按键排序的对象,你可以这样做

variable_list = [variable[i] for i in range(len(selector))]

【讨论】:

  • 这并不是我真正要问的,但我喜欢这个解决方案,因为我认为线性访问一个列表然后随机访问一个字典可能比我的示例中随机访问一个列表更快,但是有在 ipython 中用 %timeit 对其进行了基准测试,这似乎比我的循环慢两倍左右。如果您愿意,我可以在您的解决方案末尾附加我的基准测试代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-10-23
  • 1970-01-01
  • 1970-01-01
  • 2016-02-21
  • 2015-02-04
相关资源
最近更新 更多