2
$\begingroup$

Say I have a "seed" SparseArray e.g. m=SparseArray[{1->1}]. How do I add a rule at a position that has not yet been defined e.g. 5->5to get a list of rules {1}->1, (5)->5? I want to build up the sparse array an element at a time. I don't want to have to normalise it as that would appear to defeat the purpose of sparse arrays

It seems like this should be simple.

$\endgroup$
4
  • 2
    $\begingroup$ Possible duplicate of Efficient by-element updates to SparseArrays $\endgroup$
    – Jason B.
    Jun 15, 2018 at 17:57
  • 1
    $\begingroup$ Building SparseArrays entry-by-entry cannot be efficient. $\endgroup$ Jun 15, 2018 at 18:13
  • $\begingroup$ Are you reading the array while building it, or only writing to it? If only writing, you don't need to create a SparseArray. The rules are sufficient. If you need a little bit of reading, consider Association, AssociateTo for updating, and Lookup (with a default of 0) for reading. $\endgroup$
    – Szabolcs
    Jun 15, 2018 at 18:26
  • $\begingroup$ In the end I used an Association. I was misunderstanding SparseArray semantics. $\endgroup$
    – David G
    Jun 19, 2018 at 21:01

1 Answer 1

4
$\begingroup$

You need to tell the SparseArray how large it will be when you initialize it, then you can just use Part and Set to update it:

m = SparseArray[{1 -> 1}, {10}];
m[[3]] = 3
(* 3 *)

Head@m
(* SparseArray *)

Normal@m
(* {1, 0, 3, 0, 0, 0, 0, 0, 0, 0} *)

From the comments, I would suggest that an Association is a better data structure for this purpose. You can build it up efficiently, and quickly dump it to a SparseArray at the end,

data = <|1 -> 2|>;

(* do something *)
data[4] = 22;
(* do something else *)
data[233] = 55;
(* now that you are done, make a SparseArray *)
SparseArray[ Normal @ data]
(* SparseArray[Automatic, {233}, 0, {
 1, {{0, 3}, {{1}, {4}, {233}}}, {2, 22, 55}}] *)

It will work for a higher dimension array,

data = <|{1, 1} -> 2|>;
data[{45, 33}] = 22;
data[{1000, 233}] = 55;
SparseArray[ Normal @ data]

enter image description here

You can access the stored values, and provide a default value just like for an array

Lookup[data, Key[{1000, 233}], 0]
(* 55 *)

Lookup[data, Key[{1000, 234}], 0]
(* 0 *)
$\endgroup$
3
  • $\begingroup$ But I don't know how big it will be. I suppose if its internal representation is the least bit efficient I could initialise it to, say, a million elements without incurring too much of a penalty, but that seems ugly. $\endgroup$
    – David G
    Jun 15, 2018 at 17:58
  • 4
    $\begingroup$ I wonder then if SparseArray is the right tool to use for this, see the edit $\endgroup$
    – Jason B.
    Jun 15, 2018 at 18:08
  • $\begingroup$ I think that you may well be correct. Thanks. $\endgroup$
    – David G
    Jun 15, 2018 at 20:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.