# Automatically growing lists as in MATLAB?

Is there a way to add elements to a list at positions outside the current list's length? Something equivalent to the following MATLAB code snippet:

x = [1,2,3];
x(5) = 5


which returns:

x =

1     2     3     0     5

-
Sorry if the following is obvious to you (also, it's a bit off-topic): This is bad practice in MATLAB and in a direct translation also in Mathematica, as in this way new memory needs to be allocated every time you add an element and this takes a lot of time. Better preallocate by x=zeros(1,n). (Of course this doesn't matter much if you do it only once in the whole program.) – sebhofer Jul 23 '14 at 8:51

test = {1, 2, 3}

Module[{tmp = Join[list, ConstantArray[0, position - Length@list]]},
tmp[[position]] = ele; tmp]

(* {1, 2, 3, 0, 0, 55} *)


You'll probably want to add sanity checks...

-
It's neater to use PadRight. – C. E. Jul 23 '14 at 1:18
Thank you both! I thought there was a native way to do it but I was wrong! – Wolfy Jul 23 '14 at 1:33

More for my own personal edification and possible enlightenment from more experienced users, here are two other possibilities. First, Use a sparse array with a size much larger than expected.

a = Range@3;
b = SparseArray[a, 10^7];


It results in a bit of overhead

ByteCount /@ {a, b}
(* {128, 720} *)


Which decreases with increasing (initial) array size

Table[With[{a = Range@x, b = SparseArray[Range@x, 10^7]}, {x,
ByteCount[b]/ByteCount[a]}], {x, 5, 1000, 5}] // ListLinePlot


Assign away

b[[5]] = 5
(* 5 *)


Normal will return an array of Length defined in the Sparse Array

Length[Normal[b]]
(* 10000000 *)


Create a "normal" array without padding using ArrayRules

ArrayRules[b]
(* {{1} -> 1, {2} -> 2, {3} -> 3, {5} -> 5, {_} -> 0} *)
Normal@b[[1 ;; First@First@Last@Most@Sort@ArrayRules[b]]]
(* {1, 2, 3, 0, 5} *)


Second, with v10, we can emulate this behavior with Associations. This is food for thought, and I haven't thought much about it yet.

c = Association@ MapIndexed[First@#2 -> #1 &, {1, 2, 3}]
(* <|1 -> 1, 2 -> 2, 3 -> 3|> *)


Add an element with AppendTo

AppendTo[c, 5 -> 5]
(* <|1 -> 1, 2 -> 2, 3 -> 3, 5 -> 5|> *)


Note that single brackets are used in Key/Value associations

c[5]
(* 5 *)


The problem (feature?) here is that missing elements are indicated as such

c[4]
(* Missing["KeyAbsent", 4] *)


Convert to an array when you are done "messing" with the elements

SparseArray[Normal[c]] // Normal
(* {1, 2, 3, 0, 5} *)

-
+1. Turns out you can use Lookup with a default value. e.g.: Lookup[c, {1, 2, 3, 4, 5}, 0] – RunnyKine Jul 23 '14 at 2:14

why not simply:

x2[n_, a_] := PadRight[x, n, 0] + (SparseArray[n -> a] // Normal)

x2[10,5]

(*{1, 2, 3, 4, 0, 0, 0, 0, 0, 5}*)

-

Playing with UpValues:

Unprotect@Part;
Part/:Set[Part[list_,part_],value_]:=
Protect@Part;


Now you can do:

l = {1, 2, 3, 4};
l[[10]] = "x"


and get:

{1, 2, 3, 4, 0, 0, 0, 0, 0, "xx"}


Important: I do not recommend to Unprotect system symbols.

-