我的listA
和listB
大小相同。我在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}]
答案 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}}