1
$\begingroup$

Here's a 5x5 grid. Using predefined starting points, I'd like to change some sublists into something else (e.g., the values for a color, "drawing an opaque box").

list = 
{{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}}};

This seems simple enough, use the Part command to change all of the elements via:

Part[{list}, startingrow;;endingrow, startingelement;;endingelement] = assignment;

(Now use the new list for whatever you like)

This works totally as expected if your list is just a bunch of integers. Trying the one above...

list = 
{{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}}};
color1 = {0.529`, 0.808`, 0.922`};
row = 3;
start = 2;
Part[list, row - 1 ;; row + 1, start ;; start + 2] = color1;
list
(* Output:
{{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
{{1, 1, 1}, 0.529, 0.529, 0.529, {1, 1, 1}},
{{1, 1, 1}, 0.808, 0.808, 0.808, {1, 1, 1}},
{{1, 1, 1}, 0.922, 0.922, 0.922, {1, 1, 1}},
{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}}}
*)

Not good! The Part function replaced the sublists with each element of the new sublist. Putting the new sublist into a lower level almost works:

Part[list, row - 1 ;; row + 1, start ;; start + 2] = {color1};
list
(* Output:
{{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
{{1, 1, 1}, {{0.529, 0.808, 0.922}}, {{0.529, 0.808, 0.922}}, {{0.529, 0.808, 0.922}}, {1, 1, 1}},
{{1, 1, 1}, {{0.529, 0.808, 0.922}}, {{0.529, 0.808, 0.922}}, {{0.529, 0.808, 0.922}}, {1, 1, 1}},
{{1, 1, 1}, {{0.529, 0.808, 0.922}}, {{0.529, 0.808, 0.922}}, {{0.529, 0.808, 0.922}}, {1, 1, 1}},
{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}}}
*)

But now all the new sublists are a level too far down. Both Flatten with 2 arguments and FlattenAt don't appear to be able to rid specifically only these levels.

Is there a convenient way to get the desired output? (Shown Below)

{{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
{{1, 1, 1}, {0.529, 0.808, 0.922}, {0.529, 0.808, 0.922}, {0.529, 0.808, 0.922}, {1, 1, 1}},
{{1, 1, 1}, {0.529, 0.808, 0.922}, {0.529, 0.808, 0.922}, {0.529, 0.808, 0.922}, {1, 1, 1}},
{{1, 1, 1}, {0.529, 0.808, 0.922}, {0.529, 0.808, 0.922}, {0.529, 0.808, 0.922}, {1, 1, 1}},
{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}}}
$\endgroup$
1
  • $\begingroup$ When you Part assign, as a rule you should assign something that's not a list at all or an array that has the same dimensions as the Part your overwriting. If you do anything else, you should expect things like this to happen. $\endgroup$ – Sjoerd Smit Jul 31 '20 at 19:05
1
$\begingroup$

In this situation, the most concise way to do what you want that I can think of is:

With[{part := Part[list, row - 1 ;; row + 1, start ;; start + 2]},
  part = ConstantArray[color1, Most @ Dimensions[part]]
]

In short, just create a complete array that matches the dimensions of the Part your trying to overwrite. You're trying to overwrite a part of list with dimensions 3x3x3 with a list that has dimensions 3. That's why Mathematica does the assignment at a different level than you expect. The only way out of this is to match the dimensions of the old part and the new one.

$\endgroup$
1
$\begingroup$

Replace at each position using ReplacePart:

pos = Tuples[{Range[row - 1, row + 1], Range[start, start + 2]}]
new = ReplacePart[list, pos -> color1]

(This produces a new list rather than changing the old one.)

$\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.