Unsort: remembering a permutation and undoing it

后端 未结 3 936
爱一瞬间的悲伤
爱一瞬间的悲伤 2021-01-06 02:11

Suppose I have a function f that takes a vector v and returns a new vector with the elements transformed in some way. It does that by calling function g that assumes the vec

相关标签:
3条回答
  • 2021-01-06 02:23

    One possible method:

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

    gives

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

    That is,

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

    I originally learned of the above from MathGroup, [EDITED] from a post by Andrzej Kozlowski

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

    0 讨论(0)
  • 2021-01-06 02:27

    Here's a "sorting wrapper" pattern suggested by Michael Pilat earlier

    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}]
    
    0 讨论(0)
  • 2021-01-06 02:36

    Thanks to TomD and Yaroslav, here's probably the most concise/elegant way to do it:

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

    And thanks to Janus, here's a perhaps more efficient way:

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

    Note that it does 2 sorts instead of 3.

    For posterity, here's my original attempt, though I don't think it has anything to recommend it over the above:

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

    To address belisarius in the comments, the reason I'm not passing g as a parameter is because I'm thinking of g as a helper function for f. It's like I have a function f that would be easier to write if I could assume its argument was a sorted vector. So I write the version that assumes that and then do this wrapper trick.

    0 讨论(0)
提交回复
热议问题