Applying transformation of `GatherBy` to a different list

孤者浪人 提交于 2019-12-05 04:23:07

Well, first second try:

(Warning Warning ... "elegance" is an utterly subjective concept)

gBoth[lslave_, lmaster_, f_] := 
                 {Part[#, All, All, 1], Part[#, All, All, 2]} &@ 
                 GatherBy[Transpose[{lslave, lmaster}], f[#[[2]]] &]

lmaster = {1, 2, 3};
lslave = {a, b, c};  

{lslave1, lmaster1} = gBoth[lslave, lmaster, OddQ]  

Out

{{{a, c}, {b}}, {{1, 3}, {2}}}  

Edit

Note that for this code to run you must have

 Dimensions[lslave][[1;;Length[Dimensions@lmaster]]] == Dimensions@lmaster  

but the deeper internal structure of both lists could be different. For example:

lmaster = {{1, 2, 3}, {2, 3, 4}};
lslave = {{{a}, {b}, {c}}, {{a}, {b}, {c}}};

{lslave1, lmaster1} = gBoth[lslave, lmaster, #[[1]] < 3 &]

Out

{{{{{a}, {b}, {c}}, {{a}, {b}, {c}}}}, {{{1, 2, 3}, {2, 3, 4}}}}

HTH!

How about

Map[listB[[#]] &, listA1 /. Dispatch@Thread[listA -> Range[Length[listA]]]]

Edit : It actually came to my mind that this solution will have problems if listA has repeated elements.Besides, it uses the specialized knowledge that the resulting list is of constant depth 2. Here is a more general (admittedly, ugly) version, which does not care what is the resulting list structure, or whether the original list did have repeated elements :

Clear[rearrangeAs];
rearrangeAs[source_List, transformed_List, target_List] := 
  Module[{f, count, symbs = Table[Unique[], {Length[source]}]}, 
    count[_] = 0;
    f[x_, _] := x;
    MapThread[With[{cnt = ++count[#1]}, f[#1, cnt] := #2] &, {source, symbs}];
    Clear[count];
    count[_] = 0;
    Replace[transformed, x_ :> f[x, ++count[x]], {0, Infinity}] /. 
       Dispatch[Thread[symbs -> target]]]

For example,

In[94] := rearrangeAs[listA, listA1, listB]

Out[94] = {{a, c}, {b}}

I did not test, but this function should also work when the transformed list does not have a regular structure, but is some general tree

You essentially want:

Map[listB[[#]] &, listA1]

Since ListB[[{1,3,5}]] for example gives a list of the first, third, and fifth elements of ListB.

So this a very simple version of the function:

example[listA_, listB_, ordering_] := 
 Map[listB[[#]] &, GatherBy[listA, ordering]]

Its important to note that if a number is duplicated in ListA then it won't appear because of the behavior of GatherBy:

example[{1, 2, 3, 4, 5, 6, 3, 5}, {a, b, c, d, e, f, g, h}, OddQ]

{{a, c, e, c, e}, {b, d, f}}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!