2011-01-26 95 views
7

我有listAlistB大小相同。我在listA上做GatherBy,重新排列該列表。將相同重排應用於listB的優雅方法是什麼?將`GatherBy`轉換爲不同的列表

例如

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

listB1應該成爲{{a, c}, {b}}

更新 感謝有趣的想法,我終於結束了做類似的東西貝利薩留。這讓我想起了Python的的「裝飾 - 排序 - 去除裝飾」模式

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

對於真正大的列表,`grouped [[All,All,-1]]`may比使用Map更快或更快(不知道這是否與之相關螞蟻爲你的情況) – 2011-02-12 21:49:08

回答

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[[email protected]]]] == [email protected] 

但兩份名單的更深層次的內部結構可能會有所不同。例如:

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

您想基本上:

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

由於數組listB [[{1,3,5}]]例如給出數組listB的第一,第三和第五元素的列表。

所以這是一個非常簡單的版本的功能:

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

它必須注意的是,如果一個號碼在利斯塔重複的話,就不會因爲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}} 
+0

例子[{{1,3},{2,3,4},{1,2}},{a,b,c},長度]似乎不起作用 – 2011-01-27 00:20:02

2

如何

Map[listB[[#]] &, listA1 /. [email protected][listA -> Range[Length[listA]]]] 

編輯:實際上,它來到了我的腦海裏,這個解決方案將^ h如果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}} 

我沒有測試,但是這個函數也應該工作,當轉換的列表不具有常規結構,但是是一些普通樹