12
$\begingroup$

I just discovered a nice way to create intermediary columns in a list, and I would like to know if I can have some problem with it. It Works like this:

Imagine I have this list, 5x3:

SeedRandom[0]
list=RandomInteger[100,{5,3}]

Now I want to add a new blank column after position 1. I can use 0 for that, as you can see:

list=list[[All,{1,0,2,3}]]
list[[All,2]]=100
list

{{83, 100, 66, 4}, {21, 100, 71, 67}, {16, 100, 67, 76}, {28, 100, 21, 43}, {17, 100, 46, 53}}

Using 0 put List as start element of the new column.

Question: Can I have some problem in doing that way? I can't see any. And it appears to work in a nice speed.

$\endgroup$
  • 1
    $\begingroup$ is your method faster than using Insert? SeedRandom[0]; list = RandomInteger[100, {5, 3}]; list = Transpose@Insert[Transpose[list], list[[All, 2]], 2] $\endgroup$ – Nasser Nov 9 '14 at 0:43
13
$\begingroup$

I don't see any problem with this, other than unpacking as WReach beat me to writing. Part zero is simply the head of the expression, in this case the rows, here List. As another example:

x = foo[a[1, 2], b[3, 4], c[5, 6]];

x[[All, {1, 0, 2}]]
foo[a[1, a, 2], b[3, b, 4], c[5, c, 6]]

As long as you understand this and accept what obfuscation it entails it seems reasonable. Note that you aren't actually inserting a column but rather reconstructing the entire array.


Purely parenthetically, and not that I propose ever using such a thing, but for fun here's another way to insert a column using part zero:

SeedRandom[0]
list = RandomInteger[100, {5, 3}];

list[[All, 0]] = {#, 7, ##2} &;

list
{{83, 7, 66, 4},
 {21, 7, 71, 67},
 {16, 7, 67, 76},
 {28, 7, 21, 43},
 {17, 7, 46, 53}}

Hey, if we're going for weird I can code with the best of them. :^)

$\endgroup$
  • $\begingroup$ Now I want to understand what kind of Black Mathic is this! How is this pure function actually working? Any link? +1 $\endgroup$ – Murta Nov 8 '14 at 14:11
  • $\begingroup$ @Murta I added that with the hope of causing people to pause and give a second thought to "part zero" and I think it worked. :-) If we replace the heads of the rows (List) with the function we get e.g. {#, 7, ##2} &[83, 66, 4] and I think you can probably work out the rest for yourself. $\endgroup$ – Mr.Wizard Nov 8 '14 at 14:15
  • 3
    $\begingroup$ A New Kind of Map :) $\endgroup$ – WReach Nov 8 '14 at 14:16
  • 3
    $\begingroup$ @WReach Probably A New Kind of Apply would be more correct since we replace Heads here and Apply is the function which replaces Heads. $\endgroup$ – Alexey Popkov Nov 8 '14 at 14:44
  • 2
    $\begingroup$ @WReach Before I get (more?) credit that isn't due this isn't my trick; I learned it from Mike Honeychurch: (4399) $\endgroup$ – Mr.Wizard Nov 8 '14 at 14:48
14
$\begingroup$

Neat trick.

One disadvantage I see to this approach is that it unpacks a packed array:

Needs["Developer`"]

SeedRandom[0]
list = RandomInteger[100, {5, 3}]
list // PackedArrayQ
(* True *)

list[[All, {1, 0, 2, 3}]] // PackedArrayQ
(* False *)

This is because the symbol List is being repeatedly inserted into the new column. If we choose to populate the new column from another arbitrarily selected column, the array will remain packed:

list[[All, {1, 1, 2, 3}]] // PackedArrayQ
(* True *)

Since we are going to overwrite the new column anyway, it doesn't matter what values we write into it.

Having said all that, the use of zero stands out and it could be a nice idiom if array packing is not essential to the situation.

$\endgroup$
  • 1
    $\begingroup$ Interesting point about PackedArrays. It would be nice if we could just use Null as list[[All, {1, Null, 2, 3}]], and keep it packed but it's not possible. Tks +1 $\endgroup$ – Murta Nov 8 '14 at 14:06
5
$\begingroup$

I am uncertain why it is interesting to create the "blank" column with Part 0 rather than with any other Part. If I understand the problem, it is really to add a column at a location 2 and then make an assignment to that new column, so it is really irrelevant what the contents of the new column are. If that is correct, then you could

SeedRandom[0] 
list2d = RandomInteger[100, {5, 3}]
col = ConstantArray[100, 5]
MapThread[Insert[#1, #2, 2] &, {list2d, col}]  (* ht Mark *)

Or if you wanted to stick with your approach but less oddly, you could

newlist2d = list2d[[All, {1, 1, 2, 3}]]
newlist2d[[All, 2]] = 100
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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