2011-01-26 8 views
7

Tengo listA y listB del mismo tamaño. Estoy haciendo GatherBy en listA, que reorganiza esa lista. ¿Cuál es una forma elegante de aplicar una reorganización idéntica al listB?Aplicar la transformación de `GatherBy` a una lista diferente

Por ejemplo

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

listB1 debe convertirse en {{a, c}, {b}}

actualización Gracias por ideas interesantes, que finalmente terminó haciendo algo similar a Belisario. Esto me recuerda a Pitón de "decorar-tipo-Undecorate" patrón

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

Para listas realmente grandes, 'agrupadas [[Todas, Todas, -1]]' pueden ser más rápido o mucho más rápido que usar 'Map' (no estoy seguro si esto es relevante hormiga para su caso) –

Respuesta

4

Bueno, primera segundo intento:

(Atención Atención ... "elegancia" es un concepto totalmente subjetiva)

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] 

fuera

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

Editar

Tenga en cuenta que para este código se ejecute debe tener

Dimensions[lslave][[1;;Length[[email protected]]]] == [email protected] 

pero la estructura interna más profunda de ambas listas podrían ser diferentes. Por ejemplo:

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

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

fuera

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

HTH!

1

Esencialmente desea:

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

Desde ListaB [[{1,3,5}]], por ejemplo, da una lista de la primera, tercera y quinta elementos de ListaB.

Así que esta una versión muy simple de la función:

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

Es importante señalar que si un número se duplica en ListaA entonces no aparecerá debido al comportamiento de 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

ejemplo [{{1, 3}, {2, 3, 4}, {1, 2}}, {a, b, c}, Length] parece que no funciona –

+0

Sí, mi función es realmente muy simple para casos simples. ListA tiene que ser Range [Length [listB]] por lo que tiene una utilidad limitada. Lo siento, debería haber mencionado. – Searke

2

¿Qué tal

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

Editar: en realidad, me vino a la mente que esta solución h Hay problemas si listA tiene elementos repetidos. Además, utiliza el conocimiento especializado de que la lista resultante es de profundidad constante 2. Aquí es una versión más general (es cierto, feo), que no importa cuál es la estructura de la lista resultante, o si la lista original se han repetido elementos:

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

Por ejemplo,

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

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

No probé, pero esta función también debería funcionar cuando la lista transformada no tiene una estructura regular, pero es un árbol general

Cuestiones relacionadas