I am looking a good way to fill up the elements of a lower triangular matrix from a list.
I currently have this:
PadRight[#, s] & /@
Prepend[Take[elems, # + {1, 0}] & /@
Partition[Accumulate[Range[0, s - 1]], 2, 1], {}]
where elems
is the elements-list and s
is its length.
Perhaps the best way is preallocation plus a clear, procedural Do
-loop. What do you think?
You can test the above with:
s = 5
elems = Range[s(s-1)/2]
1 Answer 1
Here are a few methods for your consideration and feedback.
This one uses the core of my "Dynamic Partition" function. It is the fastest method I know for this problem. Also, perhaps refactoring the code like this makes it more intelligible.
dynP[l_, p_] :=
MapThread[l[[# ;; #2]] &, {{0}~Join~Most@# + 1, #} &@Accumulate@p]
#~PadRight~s & /@ {{}} ~Join~ dynP[elems, Range[s-1]]
This one is slightly shorter, using a different way to construct the indices, but also slightly slower, and perhaps less transparent.
#~PadRight~s & /@
Prepend[
elems~Take~# & /@
Array[{1 + # (# - 1)/2, # (# + 1)/2} &, s - 1],
{}
]
This one is terse, but slow. Legibility is debatable.
SparseArray[Join @@ Table[{i, j}, {i, s}, {j, i - 1}] -> elems, s] // MatrixForm
Here is one I just came up with, and I am quite pleased with it. I think it may be more understandable than most of the ones above.
Take[FoldList[RotateLeft, elems, Range[0, s - 1]] ~LowerTriangularize~ -1, All, s + 1]
-
\$\begingroup\$ Thanks! I'm a bit slow these days ... I find the last one quite legible, but the "good" solution for me in this case is really to use a function like your Dynamic Partitions and just pass the lengths. \$\endgroup\$Szabolcs– Szabolcs2011年10月18日 18:54:44 +00:00Commented Oct 18, 2011 at 18:54
-
\$\begingroup\$ @Szabolcs, please see the
FoldList
solution I just added. I like this one best so far, other than possibly the one leveraging dynamicPartition. \$\endgroup\$Mr.Wizard– Mr.Wizard2011年10月18日 20:06:07 +00:00Commented Oct 18, 2011 at 20:06
s
andelems
. If you run the code with these and look at theMatrixForm
of the result, you'll see what I am trying to get: a triangular matrix filled up with the elements fromelems
. \$\endgroup\$Do[ matrix[[i,j]] = ... , {i, 1, s}, {j, 1, i-1}]
. I was wondering if there's something easy to understand which is less procedural. Speed is not a priority, my matrices are smaller than 200 by 200. \$\endgroup\$Part
in place ofTake
but that is about all I can find speed wise. \$\endgroup\$