Как взять список и сгенерировать все списки возрастающей длины?

Простой вопрос для знатоков системы Mathematica:

Дан список, скажем

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

и я хочу получить обратно все списки длины 1,2,3,...Length[data], начиная с начала и до конца, так, чтобы получилось следующее

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

Я просмотрел команды в M, чтобы найти готовую для использования, и я смог (просмотрел все функции Map's и Nest*, но не вижу, как использовать для этого). Я уверен, что она там есть, но сейчас я ее не вижу.

теперь я делаю этот глупый цикл Do, чтобы построить его

m=Length[data];
First@Reap[Do[Sow[data[[1;;i]]],{i,1,m}]][[2]]

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

вопрос в том, есть ли в системе Mathematica встроенная команда для выполнения вышеописанного?

обновление 8 утра

Я удалил тесты, которые я сделал час назад и скоро выложу их снова. Мне нужно запустить их несколько раз и взять среднее значение, так как это лучший способ провести этот тест производительности.

обновление 9 утра

Хорошо, я повторно запустил тесты производительности на всех решениях, показанных ниже. 8 методов. Для каждого метода я запустил его 5 раз и взял среднее значение. Я сделал это для n={1000, 5000, 10000, 15000, 25000, 30000}, где n - длина исходного списка для обработки.

не может быть больше 30 000, закончится память. У меня всего 4 ГБ оперативной памяти.

Я сделал небольшую функцию под названием makeTable[n, methods], которая генерирует таблицу производительности для определенного n. тестовый код ниже (написан быстро, поэтому не самый чистый код, не очень функциональный, так как мне нужно идти :), но он ниже и любой может изменить/очистить его и т.д... если захочет

вывод: Метод Kguler оказался самым быстрым, а метод Thies почти таким же для больших n, (30,000), так что для всех практических целей, может быть методы Thies и Kguler могут быть объявлены победителями для больших n? Но поскольку Кгулер также быстрее всех для малых n, пока что он получает явное преимущество.

Опять же, ниже приведен тестовый код, который любой может проверить и запустить, чтобы увидеть, не допустил ли я где-нибудь ошибку. Как правильно предсказал Леонид, метод связных списков не слишком хорош для больших n.

Я думаю, нужно больше тестов, так как взять только среднее значение из 5 может быть недостаточно, а также другие соображения, которые я мог упустить. Это не точный тест, просто приблизительный, чтобы получить представление.

Я старался не использовать компьютер во время проведения тестов. Я использовал AbsoluteTiming[] для измерения процессора.

Вот скриншот сгенерированных таблиц

enter image description here

Вот код теста:

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

nasser[lst_] := Module[{m = Length[lst]},
   First@Reap[Do[Sow[lst[[1 ;; i]]], {i, 1, m}]][[2]]
   ];

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

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

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

kguler[lst_] := Module[{},
   Reverse@NestList[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[First@lst], Rest@lst]]
   ];

thies[lst_] := 
  Module[{}, 
   Drop[Reverse@
     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]] = First@AbsoluteTiming[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}
    ]
   ];

Теперь, чтобы запустить, сделайте

makeTable[1000, methods]

Внимание, не пробуйте что-то больше 30,000, если у вас не миллион ГБ, иначе M может не вернуться. Это случилось со мной, и пришлось перезагрузить компьютер.

update 12/26/11 3:30PM

Я вижу, что у Thies есть более новая версия этого алгоритма (я назвал его thies2 в таблице методов), поэтому я запустил все снова, вот обновленная таблица, я удалил версию со связанными списками, поскольку заранее известно, что она не будет быстрой для больших n, и на этот раз я запустил их каждый по 10 раз (не 5, как выше) и затем взял среднее значение). Я также запустил M заново, используя заводские настройки (на всякий случай перезапустил его, удерживая клавишу alt-shift, чтобы все настройки вернулись к исходным)

вывод на данный момент

Куглер быстрее всего для меньших n, т.е. n<20,000. Для больших n, теперь вторая версия Тиса быстрее, чем первая версия Тиса, и теперь она немного опережает метод Куглера для больших n. Поздравляю Тиса, текущего лидера в этом тесте производительности. Но для всех практических целей я бы сказал, что и метод Тиса, и метод Куглера являются самыми быстрыми для больших n, а Куглер остается самым быстрым для меньших n.

Ниже приведены таблицы и обновленный тестовый код под ними. Любой может провести тесты самостоятельно, просто на случай, если я что-то упустил из виду.

enter image description here

Текущий код теста:

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

nasser[lst_] := Module[{m = Length[lst]},
   First@Reap[Do[Sow[lst[[1 ;; i]]], {i, 1, m}]][[2]]
   ];

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

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

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

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

   ];

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

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

thies2[lst_] := 
  Module[{}, 
   Drop[Reverse@
     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]] = First@AbsoluteTiming[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}
    ]
   ];

Для запуска введите

n=1000
makeTable[n, methods]

Спасибо всем за их ответы, я узнал из них все.

6
задан Nasser 26 December 2011 в 22:12
поделиться