2011-12-26 21 views
6

Cualquier pregunta fácil para los expertos en Mathematica aquí:¿Cómo tomar una lista y generar todas las listas de mayor longitud?

dado una lista, dicen

Clear[a, b, c]; 
data = {a, b, c}; 

y yo quiero volver todas las listas de longitud 1,2,3,...Length[data] empezando desde el principio hasta el final, por lo que tengo lo siguiente para el anterior

out = {{a}, {a, b}, {a, b, c}} 

miré a los comandos M para encontrar una lista para su uso, y pude (mirado a todas las funciones del nido de Mapa y *, pero no es que yo puedo ver cómo utilizar para esto). Estoy seguro de que está allí, pero no lo estoy viendo ahora.

ahora ya esta tonta bucle Do construirlo

m=Length[data]; 
[email protected][Do[Sow[data[[1;;i]]],{i,1,m}]][[2]] 

{{a},{a,b},{a,b,c}} 

pregunta es: ¿Mathematica tiene una acumulación de comando para hacer lo anterior?

actualización 08 a.m.

He eliminado las pruebas que he hecho hace una hora y va a reposting ellos de nuevo pronto. Necesito ejecutarlos varias veces y tomar un promedio, ya que es la mejor manera de hacer esta prueba de rendimiento.

actualización 09 a.m.

Ok, he volver a ejecutar las pruebas de rendimiento en todas las soluciones que se muestran a continuación. 8 métodos. Para cada método, lo ejecuto 5 veces y tomé el promedio. Lo hice para n={1000, 5000, 10000, 15000, 25000, 30000} donde n es la longitud de la lista original para procesar.

no puede ir mucho más de 30.000, se quedará sin memoria RAM. Solo tengo 4 GB de ram.

Hice una pequeña función llamada makeTable[n, methods] que genera la tabla de rendimiento para n específico. el código de prueba está debajo (escrito rápidamente así que no es el código más limpio, no es muy funcional, ya que tengo que ir :), pero está abajo y cualquiera puede cambiarlo/limpiarlo, etc ... si lo desean

conclusión: método Kguler fue el más rápido, con el método de Thies casi el mismo para n grande, (30000), por lo que a efectos prácticos, puede ser Thies y Kguler métodos pueden ser declarados como los ganadores de gran n? Pero dado que Kguler también es el más rápido para n pequeña, hasta ahora, tiene la ventaja clara.

De nuevo, el código de prueba está debajo para que cualquiera pueda verificarlo y ejecutarlo para ver si podría haber cometido un error en alguna parte. Como Leonid predijo correctamente, el método de lista vinculada no le fue demasiado bien a n grande.

Creo que se necesitan más pruebas, ya que solo tomar la media de 5 podría no ser suficiente, también otras consideraciones que podría haber pasado por alto. Esta no es una prueba exacta, solo una aproximada para tener una idea.

Traté de no usar el PC tanto durante la ejecución de las pruebas. Usé AbsoluteTiming [] para medir la CPU.

Aquí es captura de pantalla de las tablas generadas

enter image description here

Aquí está el código de prueba:

methods = {nasser, wizard1, wizard2, wizard3, kguler, leonid1, 
    leonid2, thies}; 
AppendTo[$ContextPath, "Internal`"]; 
ClearAll[linkedList, leonid2]; 
SetAttributes[linkedList, HoldAllComplete]; 

nasser[lst_] := Module[{m = Length[lst]}, 
    [email protected][Do[Sow[lst[[1 ;; i]]], {i, 1, m}]][[2]] 
    ]; 

wizard1[lst_] := Module[{}, 
    Take[lst, #] & /@ [email protected]@lst 
    ]; 

wizard2[lst_] := Module[{}, 
    Table[Take[#, i], {i, [email protected]#}] & @lst 
    ]; 

wizard3[lst_] := Module[{}, 
    [email protected][Append, {}, #] & @lst 
    ]; 

kguler[lst_] := Module[{}, 
    [email protected][Most, #, Length[#] - 1] & @lst 

    ]; 

leonid1[lst_] := Module[{b = Bag[{}]}, 
    Map[(StuffBag[b, #]; BagPart[b, All]) &, lst] 
    ]; 

leonid2[lst_] := Module[{}, 
    Map[List @@ Flatten[#, Infinity, linkedList] &, 
    FoldList[linkedList, linkedList[[email protected]], [email protected]]] 
    ]; 

thies[lst_] := 
    Module[{}, 
    Drop[[email protected] 
    FixedPointList[If[Length[#] > 0, Most, Identity][#] &, lst], 2] 
    ]; 

makeTable[n_, methods_] := 
    Module[{nTests = Length[methods], nTries = 5, i, j, tests, lst}, 
    lst = Table[RandomReal[], {n}]; 

    tests = Table[0, {nTests}, {nTries}]; 

    For[i = 1, i <= nTests, i++, 
    For[j = 1, j <= nTries, j++, 
     tests[[i, j]] = [email protected][methods[[i]][lst] ] 
    ] 
    ]; 

    tbl = Table[{ToString[methods[[i]]], Mean[ tests[[i, All]] ]}, {i, 
     nTests}] ; 

    Grid[Join[{{"method", "cpu"}}, tbl], 
    Frame -> All, FrameStyle -> Directive[Thickness[.005], Gray], 
    Spacings -> {0.5, 1} 
    ] 
    ]; 

ahora para ejecutar, hacer

makeTable[1000, methods] 

Advertencia, no lo hacen pruebe algo más de 30,000 a menos que tenga un billón de GB, de lo contrario M podría no regreso. Me pasó a mí y tuve que reiniciar la PC.

actualización 12/26/11 15:30

veo que Thies tiene una versión más reciente de este algoritmo (que lo llamaron thies2 en la tabla de métodos), por lo que volver a ejecutar todo de nuevo, aquí es la tabla actualizada, eliminé la versión de la lista enlazada ya que se sabe de antemano que no será rápida para n grande, y esta vez, la ejecuto cada una 10 veces (no 5 como arriba) y luego tomé la media). También empecé ajuste de fábrica usando fresca M (reiniciado la celebración de teclas ALT-SHIFT para que todos los ajustes están de vuelta a la configuración original por si acaso)

conclusión hasta ahora

Kugler es más rápido para los pequeños n, es decir, n < 20,000. Para una n mayor, ahora la segunda versión de Thies es más rápida que la versión 1 de Thies y ahora avanza muy ligeramente por delante del método de Kugler para n grande. Felicidades a Thies, el líder actual en esta prueba de rendimiento. Pero para todos los propósitos prácticos, diría que los métodos de Thies y Kugler son los más rápidos para n grande, y Kugler sigue siendo el más rápido para n más pequeños.

A continuación se muestran las tablas y el código de prueba actualizado debajo de ellas. Cualquiera es libre de ejecutar las pruebas por sí mismo, en caso de que pueda pasar por alto algo.

enter image description here

El código de prueba actual:

$MinPrecision = $MachinePrecision; 
$MaxPrecision = $MachinePrecision; 
methods = {nasser, wizard1, wizard2, wizard3, kguler, leonid, thies1, 
    thies2}; 
AppendTo[$ContextPath, "Internal`"]; 

nasser[lst_] := Module[{m = Length[lst]}, 
    [email protected][Do[Sow[lst[[1 ;; i]]], {i, 1, m}]][[2]] 
    ]; 

wizard1[lst_] := Module[{}, 
    Take[lst, #] & /@ [email protected]@lst 
    ]; 

wizard2[lst_] := Module[{}, 
    Table[Take[#, i], {i, [email protected]#}] & @lst 
    ]; 

wizard3[lst_] := Module[{}, 
    [email protected][Append, {}, #] & @lst 
    ]; 

kguler[lst_] := Module[{}, 
    [email protected][Most, #, Length[#] - 1] & @lst 

    ]; 

leonid[lst_] := Module[{b = Bag[{}]}, 
    Map[(StuffBag[b, #]; BagPart[b, All]) &, lst] 
    ]; 

thies1[lst_] := 
    Module[{}, 
    Drop[[email protected] 
    FixedPointList[If[Length[#] > 0, Most, Identity][#] &, lst], 2] 
    ]; 

thies2[lst_] := 
    Module[{}, 
    Drop[[email protected] 
    FixedPointList[If[# =!= {}, Most, Identity][#] &, lst], 2] 
    ]; 

makeTable[n_Integer, methods_List] := 
    Module[{nTests = Length[methods], nTries = 10, i, j, tests, lst}, 
    lst = Table[RandomReal[], {n}]; 

    tests = Table[0, {nTests}, {nTries}]; 

    For[i = 1, i <= nTests, i++, 
    For[j = 1, j <= nTries, j++, 
     tests[[i, j]] = [email protected][methods[[i]][lst] ] 
    ] 
    ]; 

    tbl = Table[{ToString[methods[[i]]], Mean[ tests[[i, All]] ]}, {i, 
     nTests}] ; 

    Grid[Join[{{"method", "cpu"}}, tbl], 
    Frame -> All, FrameStyle -> Directive[Thickness[.005], Gray], 
    Spacings -> {0.5, 1} 
    ] 
    ]; 

Para ejecutar tipo

n=1000 
makeTable[n, methods] 

Gracias por todos por sus respuestas, he aprendido de todos ellos.

+0

Extraño, cuando mi Mathematica 8 está agotada, muere y en ocasiones mata a Google Chrome, pero no tengo que reiniciar la PC. – Nakilon

+0

@Nakilon, NO tuve que reiniciar, si esperé el tiempo suficiente, pero ni siquiera pude activar el administrador de tareas de Windows para matar el proceso, ya que la memoria era muy baja. Todo el escritorio no fue receptivo. El ariete virtual se estaba agitando y nada respondía. Es más fácil reiniciar que esperar quién sabe durante cuánto tiempo. M no murió, pero todavía estaba funcionando cuando reinicié. – Nasser

+1

Nasser, ¿has probado [este método] (http://stackoverflow.com/a/7862223/618728) para evitar eso? No puedo, ya que uso v7. –

Respuesta

3

Otra idea:

Inits[l_] := Drop[[email protected][ 
       If[Length[#] > 0, Most, Identity][#] &, 
       l 
      ], 2]; 

Actualización:

Esta versión es un poco más rápido al omitir el cálculo de la longitud de cada vez:

Inits2[l_] := Drop[[email protected][ 
       If[# =!= {}, Most, Identity][#] &, 
       l 
       ], 2]; 
7

Puede utilizar

f = [email protected][Most, #, Length[#] - 1] & 

[email protected]{a,b,c,d,e} da {{a}, {a, b}, {a, b, c}, {a, b, c, d}, {a, b, c, d, e}}.

Una alternativa usando ReplaceList - mucho más lento que f, pero ... ¿por qué no?:

g = ReplaceList[#, {x__, ___} -> {x}] & 
+0

Su solución 'alternativa' no funcionó tan bien como la anterior. Más lento en gran cantidad. Podrías probarlo tú mismo para decir n = 20,000 y verás. Tengo 6,6 segundos de tiempo de CPU, frente a 0,9 para el primero. – Nasser

+1

@Nasser, esto no fue diseñado para el concurso de velocidad, es muy lento. Pensé que era una aplicación interesante de una función y patrones incorporados. Por cierto, muchas gracias por todos sus esfuerzos en la evaluación de los métodos sugeridos. – kglr

4

propongo esto:

runs[lst_] := Take[lst, #] & /@ [email protected]@lst 

O esto:

runs2 = Table[Take[#, i], {i, [email protected]#}] &; 

respuesta de kguler me inspiró a escribir esto:

[email protected][Append, {}, #] & 

Pero esto es más lento que su método debido a de Mathematica agrega lentamente.

+0

+1, buena y directa solución. No pensé en Take. – Nasser

+0

también me gusta más +1 – kglr

+0

@kguler ¿A qué método se refiere? su respuesta, que ya he votado, es más del doble de rápida que mi método 'FoldList' debido a la * lenta de * Mathematica. También es marginalmente más rápido que los métodos 'Take ', que no anticipé. –

4

Aquí hay otro método que es más o menos tan eficaz como la que implica Take, pero utiliza la funcionalidad Internal`Bag:

AppendTo[$ContextPath, "Internal`"]; 
runsB[lst_] := 
    Module[{b = Bag[{}]}, Map[(StuffBag[b, #]; BagPart[b, All]) &, lst]]; 

No pretendo que es más sencilla que la basado en Take, pero parece ser un ejemplo simple de Internal`Bag en el trabajo, ya que este es exactamente el tipo de problema para el cual se pueden usar con éxito (y podría haber casos en los que las listas de posiciones explícitas no estarían disponibles o serían costosas de calcular).

sólo para comparar, la solución basada en listas enlazadas:

ClearAll[linkedList, runsLL]; 
SetAttributes[linkedList, HoldAllComplete]; 
runsLL[lst_] := 
    Map[List @@ Flatten[#, Infinity, linkedList] &, 
    FoldList[linkedList, linkedList[[email protected]], [email protected]]] 

habrá un orden de magnitud más lento en grandes listas.

0

Probablemente no es el más eficiente, pero otro enfoque:

dow[lst_] := lst[[1 ;; #]] & /@ [email protected]@lst 

Por ejemplo:

dow[{a, b, c, d, ee}] 

da:

{{a}, {a, b}, {a, b, c}, {a, b, c, d} , {a, b, c, d, ee}}

+1

TomD, creo que su método es el mismo que el del primer método de Mr.Wizard. – Nasser

Cuestiones relacionadas