Unsort:记住排列并撤消它

时间:2010-12-28 10:05:50

标签: sorting wolfram-mathematica permutation

假设我有一个函数f,它接受一个向量v并返回一个新的向量,其元素以某种方式转换。 它通过调用假定向量被排序的函数g来做到这一点。 所以我想要像这样定义f:

f[v_] := Module[{s, r},
  s = Sort[v];  (* remember the permutation applied in order to sort v *)
  r = g[s];
  Unsort[r]     (* apply the inverse of that permutation *)
]

“Unsort”的最佳方式是什么?

或者,我们是否真的很想要,并以某种方式工作:

answer = Unsort[g[Sort[v]]];

增加:让我们以玩具为例来具体化。 假设我们想要一个带有向量的函数f,并通过向每个元素添加下一个最小元素(如果有的话)来对其进行转换。 如果我们假设向量是有序的,那么这很容易编写,所以让我们编写一个辅助函数g来做出这样的假设:

g[v_] := v + Prepend[Most@v, 0]

现在我们真正想要的函数f,无论v是否有效,它都能正常工作:

f[v_] := (* remember the order; 
            sort it;
            call g on it;
            put it back in the original order;
            return it
         *)

3 个答案:

答案 0 :(得分:6)

一种可能的方法:

 mylist = {c, 1, a, b, 2, 4, h, \[Pi]}
    g /@ (Sort@mylist)[[Ordering@Ordering@mylist]]

给出

{g [c],g 1,g [a],g [b],g [2],g [4],g [h],g [[Pi]]

即,

(Sort@mylist)[[Ordering@Ordering@mylist]] == mylist

我最初从MathGroup获得了上述内容,[编辑]来自Andrzej Kozlowski的帖子

http://forums.wolfram.com/mathgroup/archive/2007/Jun/msg00920.html

答案 1 :(得分:3)

这是Michael Pilat早先的“排序包装”模式suggested

Clear[g];
g[a_] := If[OrderedQ[a], a^2, Print["Failed"]];
g[{3, 2, 1}]
g[a_] := g[Sort@a][[Ordering@Ordering@a]] /; Not[OrderedQ[a]];
g[{3, 2, 1}]

答案 2 :(得分:2)

感谢TomD和Yaroslav,这可能是最简洁/优雅的方式:

f[v_] := g[Sort@v][[Ordering@Ordering@v]]

感谢Janus,这可能是一种更有效的方式:

f[v_] := With[{o = Ordering@v}, g[v[[o]]][[Ordering@o]]]

请注意,它分为2种而不是3种。

对于后人来说,这是我最初的尝试,虽然我认为没有任何建议可以通过以上方式推荐:

f[v_] := With[{o = Ordering[v]}, Sort[Transpose[{o,g[v[[o]]]}]][[All,-1]]]

为了解释评论中的belisarius,我之所以没有将g作为参数传递是因为我认为g是f的辅助函数。 就像我有一个更容易编写的函数f,如果我可以假设它的参数是一个有序向量。 所以我编写假定的版本,然后执行此包装技巧。