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
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}*)
test = {1, 2, 3}
addEm[list_, position_, ele_] :=
Module[{tmp = Join[list, ConstantArray[0, position - Length@list]]},
tmp[[position]] = ele; tmp]
addEm[test, 6, 55]
(* {1, 2, 3, 0, 0, 55} *)
You'll probably want to add sanity checks...
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} *)
Lookup with a default value. e.g.: Lookup[c, {1, 2, 3, 4, 5}, 0]
– RunnyKine
Jul 23 '14 at 02:14
Playing with UpValues:
Unprotect@Part;
Part/:Set[Part[list_,part_],value_]:=
list=MapAt[value&,If[Length@list<part,PadRight[list,part],list],part]
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.
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 08:51