模拟 Length 函数来获取列表的长度

发布于 2024-12-11 20:29:42 字数 753 浏览 0 评论 0原文

我正在尝试模拟 Mathematica v.8 中的 Length 函数来获取列表的长度。鉴于以下事实:

  • 空列表表示为 {}
  • l = Rest[l] 将没有第一个元素的列表 l 分配给 l (这是一个列表)
  • While 循环

这是我使用 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. >>

I'm trying to simulate the Length function in Mathematica v.8 to get the length of a list. Given this facts:

  • Empty list is represented as {}
  • l = Rest[l] assigns to l (which is a list) the list l without the first element
  • a While loop

It's my first year using mathematica and I'm not too good at this so there's probably something (or everything) wrong with what I'm doing:

Ej1[l_List] := Module[{i, v},
v = {{}};
i = 1;
While[l != v, l = Rest[l]; i++]
Return[i]
]

l={a,b,c,d,e};

When I try to run it the loop never ends and it gives me this warnings:

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. >>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

少钕鈤記 2024-12-18 20:29:42

主要问题是您试图修改输入变量 l,这是不可能的,并且缺少分号。

Ej1[l_List] := Module[{i = 0, v = {}, thisl},
  thisl = l;
  While[thisl != v, thisl = Rest[thisl]; i++];
  i]

The main problems were that you were trying to modify the input variable, l, which is not possible, and you had a missing semi-colon.

Ej1[l_List] := Module[{i = 0, v = {}, thisl},
  thisl = l;
  While[thisl != v, thisl = Rest[thisl]; i++];
  i]
青春有你 2024-12-18 20:29:42

您还可以使用 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} *)

You can also use NestWhile:

Clear[f];
f[l_List] := NestWhile[{Rest[#[[1]]], (#[[2]]) + 1} &, {l, 0}, 
   (#[[1]] != {}) &][[2]]

This code isn't bounded by $RecursionLimit or $IterationLimit so it also works for very large lists. The downside is that it isn't very efficient since in every iteration step a copy is made of the remaining list. A faster way of counting elements in a list is to do something like

f2[l_List] := Fold[(# + 1) &, 0, l]

As a comparison:

list=RandomReal[1,10000];
Timing[f[list]]
(* ==> {3.35747, 10000} *)

Timing[f2[list]]
(* ==> {0.000658, 10000} *)
尹雨沫 2024-12-18 20:29:42
length[myList_List] := Module[{x = 0}, Scan[x++ &, myList]; x]

length[{a, b, c, d, e, f, g}]

==> 7
length[myList_List] := Module[{x = 0}, Scan[x++ &, myList]; x]

length[{a, b, c, d, e, f, g}]

==> 7
暮光沉寂 2024-12-18 20:29:42

递归地,使用 If[]

ClearAll[f];

f[l_List, i_: 0] := If[l != {}, f[Rest[l], i + 1], i];

f[{1,2}]
(*
-> 2
*)

Recursively, using If[]:

ClearAll[f];

f[l_List, i_: 0] := If[l != {}, f[Rest[l], i + 1], i];

f[{1,2}]
(*
-> 2
*)
时光瘦了 2024-12-18 20:29:42

这是另一个递归解决方案,我认为这是相当惯用的函数式编程:

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

Here is yet another recursive solution, in what I would argue is fairly idiomatic functional programming:

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
独﹏钓一江月 2024-12-18 20:29:42

与贝利萨留相同,但没有显式编写 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
*)

Same as belisarius but without explicitly writing 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
*)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文