我正在使用mathematica 7,我正在尝试使用单链表(~50,000个元素)来避免在动态列表中使用AppendTo来提高速度。 在这个测试中,我可以创建一个包含10个元素的列表,如下所示
list1 = Fold[{#1, #2} &, {}, RandomInteger[10^5, 10]]
我尝试使用Part
这样访问它(访问随机元素100次)
Timing[list1[[Sequence @@ ConstantArray[1, #], 2]] & /@RandomInteger[{1,10}, 100]]
这适用于小型列表(如上所述)。由于我不理解的原因,当列表包含更多元素(如10 ^ 4)时,这会导致内核死亡。我试过环顾这个网站&在其他地方,但只是无法弄清楚我应该如何使用链表。我甚至试图使用不同的实现,如f[e1,f[e2,f[e3,...f[]...]]]
,但我不知道一个很好的方式来访问&使用此方案时操纵元素。我想这个问题必须要做{/ {1}},但我不知道如何绕过它。
特别是我希望能够使用
$RecursionLimit
在我的代码中。同样,当列表很小但是最终崩溃内核以获得更大的列表时,这种方法也适用。奇怪的是内核并不总是崩溃,而只是随机地用于大型列表。这听起来类似于here on SE所描述的内容,但我不知道该讨论是否相关。真的,我只需要帮助修改LL元素和&在mathematica中正确使用LL。
提前致谢。
答案 0 :(得分:3)
我可以确认崩溃,但只有明显更深的Part
规范:
n = 5000000;
list1 = Fold[List, {}, RandomInteger[10^5, n]];
Do[
list1[[Sequence @@ ConstantArray[1, i], 2]] = "token"; Print[i],
{i, 100000, 200000, 10000}
]
100000 110000 120000 130000 140000 150000 160000 170000
因此,在我的系统上,崩溃发生的深度超过170,000。至少在这个深度,只有在分配一个部分而不是仅仅提取一个部分时,它也会发生:
Timing[
list1[[##, 2]] & @@ ConstantArray[1, #] & /@ RandomInteger[{1, n - 1}, 10]
]
{1.03, {77041, 74008, 29990, 13286, 12762, 48702, 76027, 25009, 31267, 1887}}
作为替代方案,我建议使用Internal`
*Bag*
functions。
n = 5000000;
list2 = Internal`Bag @ RandomInteger[10^5, n]; (* fill our Bag *)
Internal`StuffBag[list2, 27182]; (* add an element to the Bag *)
Internal`BagLength @ list2 (* check the length of our Bag *)
5000001
pos = RandomInteger[{1, n}, 10]; (* pick ten random positions *)
(* assign to those positions values 1 through 10 *)
MapIndexed[
(Internal`BagPart[list2, #] = #2[[1]]) &,
pos
];
Internal`BagPart[list2, pos] (* check the contents of those positions *)
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
(* convert our Bag into a standard list *)
flat = Internal`BagPart[list2, All];
flat[[pos]] (* check the contents again *)
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
Last @ flat (* check that the element we appended is still there *)
27182