How can I extract parts from a ragged nested list?

I have given the following list

list = {a, {b, c, d, e}, {e, f, h, i}}


Is there a direct way to use Part specification to get e.g. {a,b,e} or {a,c,f}. I know about Flatten or Append of course, but want to avoid it in my specific case.

Something like

list[[1, {{2, 1}, {3, 1}}]]


doesn't seem to work, unfortunately.

• Extract[list, {{1}, {2, 1}, {3, 1}}] yields {a,b,e}. Nov 30, 2017 at 10:11
• So often I hear people ask "How do I do X?" in Mathematica when the answer is simply "Use the function that is called X". Nov 30, 2017 at 10:30

5 Answers

Using Part you could do something like the following:

list = {a, {b, c, d, e}, {e, f, h, i}}
Part[list, ##] & @@ # & /@ {{1}, {2, 1}, {3, 1}}

(* Out[22]= {a, b, e} *)


but then again, Extract is the builtin with exactly this functionality:

Extract[list, {{1}, {2, 1}, {3, 1}}]
(* Out[23]= {a, b, e} *)

• Ok thank you for your answers/comments. I think I will deal with Extract then, though need to map it somehow, since I can not specify it manually for a huge array. This should be manageable though. Nov 30, 2017 at 10:16
• The first approach can be shortened to Part[list, ##] & @@@ {{1}, {2, 1}, {3, 1}} Nov 30, 2017 at 13:50

This seems to work, although I am not sure I fully understand why.

#& @@@ list


{a, b, e}

#2 & @@@ list


{a, c, f}

In addition (etc):

#3 & @@@ list


{a, d, h}

Original Attempt

list // Flatten[{#[[1]], #[[2 ;;, 1]]}] &


{a, b, e}

list // Flatten[{#[[1]], #[[2 ;;, 2]]}] &


{a, c, f}

• it works like that because @@@ means Apply at the second level, so that f @@@ {{a}, {b, c, d, e}, {e, f, h, i}} is equivalent to {f[a], f[b, c, d, e], f[e, f, h, i]}. When you then write #i & @@@ list you are asking for the $i$-th element of the arguments in the f example above
– glS
Nov 30, 2017 at 12:46
• @glS - From documentation for Apply: "Apply[f, expr, {1}] or f @@@ expr replaces heads at level 1 of expr by f." Nov 30, 2017 at 13:39
• @glS In addition to Bob Hanlon's comment,list is {a, {b, c, d, e}, {e, f, h, i}} not {{a}, {b, c, d, e}, {e, f, h, i}}. For example, Flatten[{{a}, {b, c, d, e}, {e, f, h, i}}, {{2}}][[1]] works for part one of OP, but Flatten[list, {{2}}] gives an error. Even if we accept that #& @@@ list should (?) work, I (naively?) expected #2& @@@ list to give an error. But thanks for your comment. Obviously I am missing something ... Nov 30, 2017 at 13:59
• @tomd From the docs of Apply -> possible issues : "Applying to atomic objects that do not have subparts effectively does nothing: f@@a (* a *). Of course, this gets into the question/issue of what exactly a subpart of an atom is, but at least it's clear what happens to symbols. Nov 30, 2017 at 14:08
• Btw, Big +1, because I use Apply all the time and never knew it had this effect on symbols. Nov 30, 2017 at 14:09

ReplacePart may be interesting for complicated ragged nested list :

list = {a, {b, c, d, e}, {e, f, h, i}}
Reap[ReplacePart[list,x: Alternatives[{1}, {2, 1}, {3, 1}] :> Sow[Extract[list,x]]]][[2,1]]


{a, b, e}

One advantage is that there isn't any warning message if some specified parts do not exist.

Other advantages/drawbacks are given here

list = {a, {b, c, d, e}, {e, f, h, i}};

Extract[list, #] & /@ Table[{{1}, {2, i}, {3, i}}, {i, 4}]


or equivalently

  Extract[list, #] & /@ {{1}, {2, #}, {3, #}} & /@ Range@4

{{a, b, e}, {a, c, f}, {a, d, h}, {a, e, i}}


If you you create a list for the first parameter a->{a,a,a,a} the solution of your problem is

Transpose[{{a, a, a, a}, {b, c, d, e}, {e, f, h, i}}]