【问题标题】:Unsort: remembering a permutation and undoing itUnsort:记住一个排列并撤消它
【发布时间】:2010-12-28 10:05:49
【问题描述】:

假设我有一个函数 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
         *)

【问题讨论】:

    标签: sorting wolfram-mathematica permutation


    【解决方案1】:

    一种可能的方法:

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

    给予

    {g[c], g1, 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

    【讨论】:

    • 排序^(2n) === 排序^2 ;订购^(2n+1) === 订购:D
    【解决方案2】:

    这是 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}]
    

    【讨论】:

    • 起初这让我很困惑,我想是因为我们在函数 g 是什么的问题上并不完全一致。请参阅我的答案的更新。但是,等等,我猜你在这里做的是通过拥有两个版本的 f 来避免对单独的辅助函数(我称之为 g)的需要。聪明的!我认为如果你在这里去掉 g ,这将不会那么混乱。
    【解决方案3】:

    感谢 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]]]
    

    为了解决 cmets 中的 belisarius,我没有将 g 作为参数传递的原因是因为我将 g 视为 f 的辅助函数。 就像我有一个函数 f ,如果我可以假设它的参数是一个排序的向量,它会更容易编写。 所以我写了假设的版本,然后做这个包装技巧。

    【讨论】:

    • 或许最好将g作为参数传递。
    • 或者效率稍微高一点,把你原来的改成With[{o = Ordering[v]}, Part[g[v[[o]]]],Ordering[o]]]
    猜你喜欢
    • 1970-01-01
    • 2011-11-15
    • 2013-03-27
    • 2016-02-04
    • 1970-01-01
    • 2021-05-19
    • 1970-01-01
    • 2015-01-23
    • 1970-01-01
    相关资源
    最近更新 更多