Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simulating Length function to get a list's length

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. >>
like image 963
Carlos Avatar asked Oct 24 '11 11:10

Carlos


2 Answers

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]
like image 191
Chris Degnen Avatar answered Nov 10 '22 15:11

Chris Degnen


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} *)
like image 6
Heike Avatar answered Nov 10 '22 17:11

Heike