将`GatherBy`转换为不同的列表

时间:2011-01-26 22:56:26

标签: wolfram-mathematica

我的listAlistB大小相同。我在GatherBy上进行listA,重新排列该列表。将相同重新排列应用于listB的优雅方法是什么?

例如

listA = {1, 2, 3};
listB = {a, b, c};
listA1 = GatherBy[{1, 2, 3}, OddQ];

listB1应该成为{{a, c}, {b}}

更新的 感谢有趣的想法,我最终做了类似于belisarius的事情。这让我想起了Python的“decorate-sort-undecorate”模式

decorated = Thread[{listA, listB}];
grouped = GatherBy[decorated, OddQ[First[#]] &];
listB1 = Map[Last, grouped, {2}]

3 个答案:

答案 0 :(得分:4)

嗯,第一次第二次尝试:

(警告警告......“优雅”是一个完全主观的概念)

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]  

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

修改

请注意,要运行此代码,您必须

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

但两个列表的内部结构可能会有所不同。例如:

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

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

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

HTH!

答案 1 :(得分:2)

怎么样

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

编辑:实际上我想到,如果listA重复元素,这个解决方案将会出现问题。此外,它使用了结果列表具有恒定深度2的专业知识。 这是一个更通用的(诚然,丑陋的)版本,它不关心结果列表结构是什么,或者原始列表是否有重复的元素:

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

例如,

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

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

我没有测试,但是当变换后的列表没有常规结构时,这个函数也应该工作,但是是一些通用树

答案 2 :(得分:1)

你基本上想要:

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

因为ListB [[{1,3,5}]]例如给出了ListB的第一,第三和第五个元素的列表。

所以这是一个非常简单的函数版本:

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

重要的是要注意,如果ListA中的数字重复,那么由于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}}