# Part like Delete: How to delete list of columns or arbitrarily deeper levels [duplicate]

On trying to write this answer I reached the frustrating realization that I didn't have an efficient way to delete a list of columns or deeper level components in a simple way as Part gives.

Given

MatrixForm[m = Partition[Partition[Range[4 4 3], 3], 4]]


I can Delete rows {2,3} by

Delete[m, List /@ {2, 3}] // MatrixForm


But to delete the columns or deeper levels I would need to Transpose twice. For instance using something like this

rDelete[m_, row_, col_] := Delete[
Transpose[
Delete[
Transpose[m]
, List /@ col
]
], List /@ row
]


On the other hand to get a Part at any level I can easily use

Part[m, All, {1, 4}, {2, 3}] // MatrixForm


Unfortunately, All and Span are not available for Delete.

Question: How can we delete columns or whole higher levels elegantly and efficiently, as we do with Part?

• This removes the second "column" of m: Drop[m, None, {2}, None]. Drop[m, None, None, {2}] gives the complement of your Part[] example. You can judiciously combine this with Map[]/MapAt[] if you need to do several positions, since unlike Delete[], Drop[] can only remove from either a single dimension or a range of dimensions. Commented Feb 25, 2016 at 16:12
• @J.M. I guess the problem with Drop is the fact that you need to Map over the list of indexes to delete, as you say. Commented Feb 25, 2016 at 16:55
• Also: (43785) Commented Feb 26, 2016 at 23:28

You can actually use Part for that:

ClearAll[delete];
delete[expr_, specs___] :=
Module[{copy = expr},
copy[[specs]] = Sequence[];
copy
];


So that for example

delete[m, All, All, 2]

(*
{
{{1, 3}, {4, 6}, {7, 9}, {10, 12}},
{{13, 15}, {16, 18}, {19, 21}, {22, 24}},
{{25, 27}, {28, 30}, {31, 33}, {34, 36}},
{{37, 39}, {40, 42}, {43, 45}, {46, 48}}
}
*)


Note that this is not exactly equivalent to Delete in all cases, since sequence splicing is an evaluation-time effect, so the results will be different if you delete inside held expressions - in which case the method I suggested may not work.

Here is a version that would probably be free of the mentioned flaw, but will be slower:

ClearAll[deleteAlt];
deleteAlt[expr_, specs___] :=
Module[{copy = Hold[expr], tag},
copy[[1, specs]] = tag;
ReleaseHold@Delete[copy, Position[copy, tag]]
];


You can test both on say, Hold[Evaluate[m]], with the spec 1, All, All, 2, to see the difference.

• This opens for me a whole a new understanding of Sequence. Very clever! +1 Commented Feb 25, 2016 at 16:11
• The Sequence[] is replaceable with Nothing in version 10.2, I suppose. Speaking of which: MapAt[Nothing, m, {All, All, 2}]. Commented Feb 25, 2016 at 16:15
• @J.M. I am aware of Nothing, but haven't yet gained extensive experience with it, unlike with Sequence. As to MapAt, this is a possibility, but it was known to have efficiency issues in the past, for large number of positions mapped. I didn't have the time to check it now, so I didn't go that way - for in-place assignments with Part, it has been known that it has excellent efficiency in all cases. Commented Feb 25, 2016 at 16:24
• I don't want to move the goalpost, I'm grateful for your answer and the code is unambiguous. What I was expecting (naively?) is deleted columns, rows and higher orders all across the array, like in my example with rDelete, where all the elements have the same length. But this already solves most of what I wanted nicely. Commented Feb 25, 2016 at 18:41
• @rhermans This is then different semantics. Here is a version that works that way: ClearAll[delete2];delete2[expr_, part_, rest___] :=Module[{copy = expr}, copy[[part]] = Sequence[];Map[delete2[#, rest] &, copy]]; delete2[expr_] := expr;. But it won't be as efficient as the ones I posted before. Commented Feb 25, 2016 at 19:04

You may use ReplacePart and Nothing with Blank (_) for All.

Delete second entry of all submatrices

ReplacePart[m, {_, _, 2} -> Nothing] // MatrixForm


Delete last column

ReplacePart[m, {_, -1} -> Nothing] // MatrixForm


and so on.

Hope this helps.

• Thanks, it does partially. How do you deal with list of columns to delete? Commented Feb 25, 2016 at 17:08
• @rhermans Alternatives : ReplacePart[m, {_, 2 | 3} -> Nothing] // MatrixForm. Commented Feb 25, 2016 at 17:21