5
$\begingroup$

Consider a big list where all the inner lists' lengths are the same

 list = {{x1, y1, z1, t1}, {x2, y2, z2, t2}, {x3, y3, z3, t3}, ...};
 elementNo = {4, 3, 2};

I want output like this,

{{x1}, {x2}, {x3}, ...}

That is, when I specify elementNo as {4, 3, 2}, I mean the elements at positions 2, 3 and 4 in the sub-lists should be removed -- I want the elements at position 1 only. When I specify elementNo as {2, 3}, I want

 {{x1, t1}, {x2, t2}, {x3, t3}, ...}

How can I do this?

$\endgroup$
6
  • $\begingroup$ Hm... okay, I guess I see now. You should describe this problem as deleting elements, as that is what it is. $\endgroup$
    – Mr.Wizard
    Commented Mar 18, 2013 at 6:07
  • $\begingroup$ @Mr.Wizard I tried for getting that output,but I didn't get it. $\endgroup$
    – subbu
    Commented Mar 18, 2013 at 6:10
  • $\begingroup$ @Mr.Wizard we have to remove the specific position elements from the main list,that specific element position getting from elementNO. $\endgroup$
    – subbu
    Commented Mar 18, 2013 at 6:12
  • $\begingroup$ I answered this. Please take the time to Accept some of the answers to your earlier questions. $\endgroup$
    – Mr.Wizard
    Commented Mar 18, 2013 at 6:15
  • $\begingroup$ @m_goldberg You're obsessive about your edits, aren't you? $\endgroup$
    – Mr.Wizard
    Commented Mar 18, 2013 at 6:52

10 Answers 10

10
$\begingroup$

Another option:

f[list_, pos_] := Module[{x = list},
  x[[All, pos]] = Sequence[];
  x]
$\endgroup$
0
4
$\begingroup$
f1[list_, spec_] := With[{sp = List /@ spec}, Delete[#, sp] & /@ list]

f1[list, {4, 3, 2}]
f1[list, {2, 3}]
{{x1}, {x2}, {x3}}
{{x1, t1}, {x2, t2}, {x3, t3}}
f2[list_, spec_] := list[[ All, Complement[Range@Length@First@list, spec] ]]

f2[list, {4, 3, 2}]
f2[list, {2, 3}]
{{x1}, {x2}, {x3}}
{{x1, t1}, {x2, t2}, {x3, t3}}
$\endgroup$
3
  • 4
    $\begingroup$ +1. Note that a more efficient form of List /@ specis Transpose[{spec}]. $\endgroup$ Commented Mar 18, 2013 at 8:33
  • $\begingroup$ @Leonid True, however I thought clarity might be better for this answer, and f2 is the higher performance method anyway. $\endgroup$
    – Mr.Wizard
    Commented Mar 18, 2013 at 10:37
  • $\begingroup$ Ok, makes sense. $\endgroup$ Commented Mar 18, 2013 at 11:11
2
$\begingroup$

Try this one

list = RandomInteger[50, {10, 4}]
new = {};
elemNo = {4, 3, 2};
new = Map[Delete[#, {{elemNo[[1]]}, {elemNo[[2]]}, {elemNo[[3]]}}] &,list]
$\endgroup$
1
  • 1
    $\begingroup$ That won't work if the elemNo list is a different length. It's also not efficiently written, as you could much more easily do: Map[Delete[#, List /@ elemNo] &, list]. This is what I did in my answer for the function f1 but with the additional optimization of doing the List /@ elemNo once and inserting it using With. $\endgroup$
    – Mr.Wizard
    Commented Mar 18, 2013 at 6:49
2
$\begingroup$

Here's another alternative:

f[list_, pos_] := With[{p = pos ~Sort~ Greater}, Fold[# ~Drop~ {#2} &, #, p] & /@ list]

f[list, {2, 3}]
(* {{x1, t1}, {x2, t2}, {x3, t3}} *)

If you can guarantee that the positions to be dropped will be input in descending order, you can drop the sorting step.

$\endgroup$
2
$\begingroup$
list = {{x1, y1, z1, t1}, {x2, y2, z2, t2}, {x3, y3, z3, t3}};
elementNo = {4, 3, 2};

MapAt[Nothing, list, Thread[{All, elementNo}]]

{{x1}, {x2}, {x3}}

$\endgroup$
1
$\begingroup$

here is the way I would do it using my Excel mindset,

list = {{x1, y1, z1, t1}, {x2, y2, z2, t2}, {x3, y3, z3, t3}};
elementNo = {4, 3, 2};
todelete = {#} & /@ Sort@elementNo
tokeep = Delete[Range@Length@First@list, todelete]
remaining = Take[list, All, tokeep]

or something similar.

$\endgroup$
1
$\begingroup$

Another way, using Outer and Extract:

data = {{x1, y1, z1, t1}, {x2, y2, z2, t2}, {x3, y3, z3, t3}};
unwanted1 = {4, 3, 2};
unwanted2 = {2, 3};

extractComplement[data_List, spec_List] :=
  Module[{dataSize, subSize, survivors},
    dataSize = Length@data;
    subSize = Length@data[[1]];
    survivors = Outer[List, Range@dataSize, Complement[Range@subSize, spec]];
    Extract[data, #] & /@ survivors]

extractComplement[data, unwanted1]

{{x1}, {x2}, {x3}}

extractComplement[data, unwanted2]

{x1, t1}, {x2, t2}, {x3, t3}

$\endgroup$
1
$\begingroup$

If all sublists are indeed of the same length, use Transpose:

Transpose@Delete[Transpose@list, List /@ elementNo]
{{x1}, {x2}, {x3}}

Note that you can use the shorthand notation for Transpose, which makes the code really short:

Mathematica graphics

With other elementNo:

elementNo = {3, 2};
Transpose@Delete[Transpose@list, List /@ elementNo]
{{x1, t1}, {x2, t2}, {x3, t3}}
$\endgroup$
2
  • $\begingroup$ While you're using Transpose how about Delete[list\[Transpose], {elementNo}\[Transpose]]\[Transpose]? Looks great in the Notebook. :-) $\endgroup$
    – Mr.Wizard
    Commented Mar 18, 2013 at 10:35
  • $\begingroup$ @Mr.Wizard I've set my PerformanceGoal to "Speed" instead of "CodeGolf". An extra Transpose might be just too much for a modern computer... :) $\endgroup$ Commented Mar 18, 2013 at 10:41
1
$\begingroup$
list = {{x1, y1, z1, t1}, {x2, y2, z2, t2}, {x3, y3, z3, t3}};

ps = {4, 3, 2};

Since Version 13.1 there is ReplaceAt:

ReplaceAt[list, _ -> Nothing, Thread[{All, ps}]]

{{x1}, {x2}, {x3}}

ReplacePart[list, {_, Alternatives @@ ps} -> Nothing]

{{x1}, {x2}, {x3}}

$\endgroup$
0
$\begingroup$

Using ArrayRules and Select:

list = {{x1, y1, z1, t1}, {x2, y2, z2, t2}, {x3, y3, z3, t3}};
ps = {4, 3, 2};

Values@Select[Rule[Last@#[[1]], {#[[2]]}] & /@ Most@ArrayRules[list], 
FreeQ[#[[1]], Alternatives @@ ps] &]

(*{{x1}, {x2}, {x3}}*)

Or using Table:

Table[If[Or @@ Thread[j == ps], Nothing, list[[i, j]]], {i, #}, {j, #}] &@Length@list

(*{{x1}, {x2}, {x3}}*)
$\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.