Применение преобразования `GatherBy` к другому списку - PullRequest
7 голосов
/ 27 января 2011

У меня listA и listB одинакового размера.Я делаю GatherBy на listA, который переупорядочивает этот список.Какой элегантный способ применить идентичные перестановки к listB?

Например,

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

Ответы [ 3 ]

4 голосов
/ 27 января 2011

Ну, первая вторая попытка:

(Предупреждение Предупреждение ... "элегантность" - это совершенно субъективная концепция)

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

Редактировать

Обратите внимание, что для запуска этого кода необходимо иметь

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

Out

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

HTH!

2 голосов
/ 27 января 2011

Как насчет

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

Я не проверял, но эта функция также должна работать, когда преобразованный список не имеет регулярной структуры, но является некоторым общим деревом

1 голос
/ 27 января 2011

По сути, вы хотите:

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}}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...