千里马:如何滚动(或移动)列表

时间:2015-09-04 15:14:23

标签: list maxima

滚动列表的最简单方法是什么?

考虑以下列表:

myList : [0,1,4,6,3]

我正在寻找一个roll()函数:

(%i0) roll(myList,1)
(%o0) [3,0,1,4,6]


(%i1) roll(myList,-1)
(%o1) [1,4,6,3,0]

我可以通过调用:

来获得相同的结果
myItem : pop(myList)
myList : append(myList,myItem)

问题是这只能在一个方向上工作(我知道没有pop_back()函数(?))并且它是一个双线性的。有没有更好的方法呢?

1 个答案:

答案 0 :(得分:2)

嗯,没有内置功能。但我认为你可以使用rest来获得你想要的效果。

(%i10) rotate (e, n) :=
   if atom(e) then e
   else block ([a : args(e)],
          apply (op(e),
                 append (rest (a, length(a) - n), rest (a, -n)))) $
(%i11) foo : [a, b, c, d, e, f, g];
(%o11)                       [a, b, c, d, e, f, g]
(%i12) rotate (foo, 2);
(%o12)                       [f, g, a, b, c, d, e]
(%i13) rotate (foo, 7);
(%o13)                       [a, b, c, d, e, f, g]

这适用于所有表达式,而不仅仅是列表。

(%i16) rotate (f(1,2,3), 2);
(%o16)                            f(2, 3, 1)

此实现不会使参数数量大于nn,但我认为处理它会很容易。

我假设rotate将较小指数的元素移动到更大的指数。同样,如果您希望默认值朝另一个方向发展,我认为这样做很容易。

编辑:实际上没有必要将op(e)args(e)分开。当rest(e, ...)不是列表时,您可以致电e,它会做正确的事情。所以更简洁的版本是:

rotate (e, n) :=
   if atom(e) then e
   else append (rest (e, length(e) - n), rest (e, -n)) $