6
$\begingroup$

I have this list as an example:

L1 = {{1, 7, 23, 31, 19}, {1, 19, 17, 35, 9}, {1, 9, 25, 37, 21}, {1, 21, 15, 33, 7}, {2, 8, 24, 34, 20}, {2, 20, 18, 38, 10}, {2, 10, 26, 36, 22}, {2, 22, 16, 32, 8}, {3, 11, 28, 34, 24}, {3, 24, 8, 32, 12}, {3, 12, 27, 31, 23}, {3, 23, 7, 33, 11}, {4, 13, 30, 36, 26}, {4, 26, 10, 38, 14}, {4, 14, 29, 37, 25}, {4, 25, 9, 35, 13}, {5, 16, 22, 36, 30}, {5, 30, 13, 35, 17}, {5, 17, 19, 31, 27}, {5, 27, 12, 32, 16}, {6, 15, 21, 37, 29}, {6, 29, 14, 38, 18}, {6, 18, 20, 34, 28}, {6, 28, 11, 33, 15}}

I want to remove all elements {1, 2, 3, 4, 5, 6} from this list to give the following list as an output:

L2 = {{7, 23, 31, 19}, {19, 17, 35, 9}, {9, 25, 37, 21}, {21, 15, 33, 7}, {8, 24, 34, 20}, {20, 18, 38, 10}, {10, 26, 36,22}, {22, 16, 32, 8}, {11, 28, 34, 24}, {24, 8, 32, 12}, {12, 27, 31, 23}, {23, 7, 33, 11}, {13, 30, 36, 26}, {26, 10, 38, 14}, {14, 29, 37, 25}, {25, 9, 35, 13}, {16, 22, 36, 30}, {30, 13, 35, 17}, {17, 19, 31, 27}, {27, 12, 32, 16}, {15, 21, 37, 29}, {29, 14, 38, 18}, {18, 20, 34, 28}, {28, 11, 33, 15}}

In this case each time the first element of a of the list {a,b,c,d,e} is removed, however this might not always be the case for other examples.

My question is what is the best way to do this. I was thinking of two for-loops, but I am sure there is a nicer way to do this.

Thank you in advance.

$\endgroup$

9 Answers 9

8
$\begingroup$
DeleteCases[L1, Alternatives @@ Range@6, {2}]

Similar to @bmf but using the levelspec argument instead of mapping.

$\endgroup$
2
  • $\begingroup$ I think this is the fastest solution $\endgroup$ Commented Sep 5, 2023 at 6:57
  • $\begingroup$ Thank you @lericr! This works perfectly $\endgroup$
    – P Teeuwen
    Commented Sep 5, 2023 at 14:20
7
$\begingroup$

I was thinking of two for-loops,

That would probably be the Fortran or C way. In Mathematica there is no need to do this. You just need to find the builtin function instead and use that.

There are at least 10 ways to do this in Mathematica. One way could be

L1 = {{1, 7, 23, 31, 19}, {1, 19, 17, 35, 9}, {1, 9, 25, 37, 21}, {1, 
   21, 15, 33, 7}, {2, 8, 24, 34, 20}, {2, 20, 18, 38, 10}, {2, 10, 
   26, 36, 22}, {2, 22, 16, 32, 8}, {3, 11, 28, 34, 24}, {3, 24, 8, 
   32, 12}, {3, 12, 27, 31, 23}, {3, 23, 7, 33, 11}, {4, 13, 30, 36, 
   26}, {4, 26, 10, 38, 14}, {4, 14, 29, 37, 25}, {4, 25, 9, 35, 
   13}, {5, 16, 22, 36, 30}, {5, 30, 13, 35, 17}, {5, 17, 19, 31, 
   27}, {5, 27, 12, 32, 16}, {6, 15, 21, 37, 29}, {6, 29, 14, 38, 
   18}, {6, 18, 20, 34, 28}, {6, 28, 11, 33, 15}}

del={1,2,3,4,5,6}
Map[DeleteElements[#,del]&,L1]

Mathematica graphics

see https://reference.wolfram.com/language/ref/DeleteElements.html

enter image description here

$\endgroup$
6
$\begingroup$

Just joining the party hoping that the following

DeleteCases[1 | 2 | 3 | 4 | 5 | 6] /@ L1;

counts as a distinct enough solution.

The check

LinearAlgebra`Private`ZeroArrayQ@Flatten[% - L2]

gives True.

Edit: there's also this that came to mind

Pick[L1, L1, Except[1 | 2 | 3 | 4 | 5 | 6, _Integer]];
LinearAlgebra`Private`ZeroArrayQ@Flatten[% - L2]
$\endgroup$
5
$\begingroup$

You can ReplaceAll such elements with Nothing, which gets removed from lists.

L1 = {{1, 7, 23, 31, 19}, {1, 19, 17, 35, 9}, {1, 9, 25, 37, 21}, {1, 
    21, 15, 33, 7}, {2, 8, 24, 34, 20}, {2, 20, 18, 38, 10}, {2, 10, 
    26, 36, 22}, {2, 22, 16, 32, 8}, {3, 11, 28, 34, 24}, {3, 24, 8, 
    32, 12}, {3, 12, 27, 31, 23}, {3, 23, 7, 33, 11}, {4, 13, 30, 36, 
    26}, {4, 26, 10, 38, 14}, {4, 14, 29, 37, 25}, {4, 25, 9, 35, 
    13}, {5, 16, 22, 36, 30}, {5, 30, 13, 35, 17}, {5, 17, 19, 31, 
    27}, {5, 27, 12, 32, 16}, {6, 15, 21, 37, 29}, {6, 29, 14, 38, 
    18}, {6, 18, 20, 34, 28}, {6, 28, 11, 33, 15}};
L2 = {{7, 23, 31, 19}, {19, 17, 35, 9}, {9, 25, 37, 21}, {21, 15, 33, 
    7}, {8, 24, 34, 20}, {20, 18, 38, 10}, {10, 26, 36, 22}, {22, 16, 
    32, 8}, {11, 28, 34, 24}, {24, 8, 32, 12}, {12, 27, 31, 23}, {23, 
    7, 33, 11}, {13, 30, 36, 26}, {26, 10, 38, 14}, {14, 29, 37, 
    25}, {25, 9, 35, 13}, {16, 22, 36, 30}, {30, 13, 35, 17}, {17, 19,
     31, 27}, {27, 12, 32, 16}, {15, 21, 37, 29}, {29, 14, 38, 
    18}, {18, 20, 34, 28}, {28, 11, 33, 15}};
L3 = L1 /. Alternatives @@ {1, 2, 3, 4, 5, 6} -> Nothing
L4 = L1 /. 1 | 2 | 3 | 4 | 5 | 6 -> Nothing (* equivalent *)
L2 == L3 == L4

Mathematica output

$\endgroup$
1
  • 3
    $\begingroup$ (+1) from me. Just a comment: this L1 /. Thread[{1, 2, 3, 4, 5, 6} -> Nothing] is more straightforward and shorter I think $\endgroup$
    – bmf
    Commented Sep 4, 2023 at 21:23
4
$\begingroup$
Clear["Global`*"];
L1 = {{1, 7, 23, 31, 19}, {1, 19, 17, 35, 9}, {1, 9, 25, 37, 21}, {1, 
    21, 15, 33, 7}, {2, 8, 24, 34, 20}, {2, 20, 18, 38, 10}, {2, 10, 
    26, 36, 22}, {2, 22, 16, 32, 8}, {3, 11, 28, 34, 24}, {3, 24, 8, 
    32, 12}, {3, 12, 27, 31, 23}, {3, 23, 7, 33, 11}, {4, 13, 30, 36, 
    26}, {4, 26, 10, 38, 14}, {4, 14, 29, 37, 25}, {4, 25, 9, 35, 
    13}, {5, 16, 22, 36, 30}, {5, 30, 13, 35, 17}, {5, 17, 19, 31, 
    27}, {5, 27, 12, 32, 16}, {6, 15, 21, 37, 29}, {6, 29, 14, 38, 
    18}, {6, 18, 20, 34, 28}, {6, 28, 11, 33, 15}};

alt = Alternatives @@ Range[6];
Delete[L1, Position[L1, alt]]

or

Pick[L1, Map[FreeQ[alt], L1, {2}]]
$\endgroup$
3
$\begingroup$
Select[! Between[#, {1, 6}] &] /@ L1

{{7, 23, 31, 19}, {19, 17, 35, 9}, {9, 25, 37, 21}, {21, 15, 33, 7}, {8, 24, 34, 20}, {20, 18, 38, 10}, {10, 26, 36, 22}, {22, 16, 32, 8}, {11, 28, 34, 24}, {24, 8, 32, 12}, {12, 27, 31, 23}, {23, 7, 33, 11}, {13, 30, 36, 26}, {26, 10, 38, 14}, {14, 29, 37, 25}, {25, 9, 35, 13}, {16, 22, 36, 30}, {30, 13, 35, 17}, {17, 19, 31, 27}, {27, 12, 32, 16}, {15, 21, 37, 29}, {29, 14, 38, 18}, {18, 20, 34, 28}, {28, 11, 33, 15}}

$\endgroup$
3
$\begingroup$
Select[Not@*Between[{1, 6}]] /@ L1

A point-free version of @eldo's solution.

If we can assume that the values are all positive integers, we could do this instead:

Select[GreaterThan[6]] /@ L1
$\endgroup$
2
$\begingroup$

Another way using Position and ReplacePart:

ReplacePart[L1, Position[L1, Alternatives @@ Range[6]] -> Nothing] === L2

(*True*)

Or using Drop for this particular case:

Drop[#, {1}] & /@ L1 === L2

(*True*)

Or using Cases for this particular case:

Cases[L1, x : {___} :> Rest@x] === L2

(*True*)
$\endgroup$
3
  • 2
    $\begingroup$ The Cases and Drop solutions work in this particular case, but the first solution is compliant with the OP. $\endgroup$
    – Syed
    Commented Sep 5, 2023 at 4:05
  • 2
    $\begingroup$ It seems that Cases and DeleteCases are somehow inverse functions; they are not. In cases such as these, you can easily use DeleteCases or Delete or DeleteElement or ReplacePart. If you choose to use Cases, you will have to write difficult patterns or re-establish list structure. $\endgroup$
    – Syed
    Commented Sep 5, 2023 at 4:44
  • $\begingroup$ Thanks mate! At this time, I add your suggestions for clarity in my answer :-) $\endgroup$ Commented Sep 5, 2023 at 13:17
1
$\begingroup$

Some more positional solutions

p = Position[L1, Alternatives @@ Range[6]];

Using Delete

r1 = Delete[p] @ L1;

Using ReplaceAt (new in 13.1)

r2 = ReplaceAt[_ :> Nothing, p] @ L1;

Using MapAt

r3 = MapAt[Nothing, p] @ L1;

r1 == r2 == r3 == L2

True

$\endgroup$

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.