假设您要对数据数组进行非对称转换,但是您希望数据关于该转换是对称的。你会
问题:在原始数据空间上进行排列以使数据恢复原状比建立反向排列要容易得多。
[示例:生成随机的前景色,与背景色相距甚远。您需要远离三种基本颜色之一,而其他两种颜色可能都是随机的。假设我的背景色是:
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)
在这个简单的案例中,事情是很容易处理的,但是让我们想象一个更复杂的案例,它具有更多的维度。它将需要一个循环来管理所有输出分配,如下所示:
for i in range(len(selector)):
variable[selector[i]] = ordered_source_tuple[i]
是否会有一种很好的python方式编写这样的赋值,它看起来像是对变量的理解列表。像这样的东西(由于左侧部分不是LValues的元组,因此显然不起作用):
(variable[i] for i in selector) = ordered_source_tuple
并找到反向排列来写这不是简单的操作
variable = ordered_source_tuple(reversed_selector)
创建新颜色,然后在分配给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)
这不再是单行代码,但是如果您像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))
当然,这或多或少与您的赋值循环等效,但是将其隐藏在某种通用函数中。
这可能是作弊,但是字典呢:
variable = dict(zip(selector, ordered_source_tuple))
如果您想将其变成按键排序的对象,则可以
variable_list = [variable[i] for i in range(len(selector))]