我正在尝试在Mathematica v.8中模拟Length函数来获取列表的长度。鉴于这一事实:
这是我使用mathematica的第一年,我对此并不太擅长,所以我正在做的事情中可能存在某些(或一切)错误:
Ej1[l_List] := Module[{i, v},
v = {{}};
i = 1;
While[l != v, l = Rest[l]; i++]
Return[i]
]
L = {A,B,C,d,E};
当我尝试运行它时,循环永远不会结束,它会给我这个警告:
Set::shape: Lists {a,b,c,d,e} and {b,c,d,e} are not the same shape. >>
Set::shape: Lists {a,b,c,d,e} and {b,c,d,e} are not the same shape. >>
Set::shape: Lists {a,b,c,d,e} and {b,c,d,e} are not the same shape. >>
General::stop: Further output of Set::shape will be suppressed during this calculation. >>
答案 0 :(得分:9)
主要问题是你试图修改输入变量l
,这是不可能的,而且你的分号丢失了。
Ej1[l_List] := Module[{i = 0, v = {}, thisl},
thisl = l;
While[thisl != v, thisl = Rest[thisl]; i++];
i]
答案 1 :(得分:6)
您还可以使用NestWhile
:
Clear[f];
f[l_List] := NestWhile[{Rest[#[[1]]], (#[[2]]) + 1} &, {l, 0},
(#[[1]] != {}) &][[2]]
此代码不受$RecursionLimit
或$IterationLimit
限制,因此它也适用于非常大的列表。缺点是效率不高,因为在每个迭代步骤中都会复制剩余的列表。计算列表中元素的更快方法是执行类似
f2[l_List] := Fold[(# + 1) &, 0, l]
作为比较:
list=RandomReal[1,10000];
Timing[f[list]]
(* ==> {3.35747, 10000} *)
Timing[f2[list]]
(* ==> {0.000658, 10000} *)
答案 2 :(得分:4)
length[myList_List] := Module[{x = 0}, Scan[x++ &, myList]; x]
length[{a, b, c, d, e, f, g}]
==> 7
答案 3 :(得分:3)
递归地使用If[]
:
ClearAll[f];
f[l_List, i_: 0] := If[l != {}, f[Rest[l], i + 1], i];
f[{1,2}]
(*
-> 2
*)
答案 4 :(得分:3)
这是另一个递归解决方案,我认为这是相当惯用的函数式编程:
myLength[{}] := 0
myLength[lis_List] := 1 + myLength[Rest[lis]]
In[47]:= myLength[{}]
Out[47]= 0
In[48]:= myLength[{1}]
Out[48]= 1
In[49]:= myLength[{1,2,3,4,5}]
Out[49]= 5
答案 5 :(得分:1)
与belisarius相同但没有明确写If
:
ClearAll[ej2];
ej2[lst_ /; (lst == {}), i_: 0] := i
ej2[lst_, i_: 0] := ej2[Rest[lst], i + 1]
ej2[{1, 2, 3, 4, 5}]
(*
5
*)