6

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.

glS
  • 7,623
  • 1
  • 21
  • 61
NeverMind
  • 1,201
  • 7
  • 9

5 Answers5

11

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} *)
glS
  • 7,623
  • 1
  • 21
  • 61
  • 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. – NeverMind Nov 30 '17 at 10:16
  • 5
    The first approach can be shortened to Part[list, ##] & @@@ {{1}, {2, 1}, {3, 1}} – Bob Hanlon Nov 30 '17 at 13:50
4

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}

user1066
  • 17,923
  • 3
  • 31
  • 49
  • 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 '17 at 12:46
  • 1
    @glS - From documentation for Apply: "Apply[f, expr, {1}] or f @@@ expr replaces heads at level 1 of expr by f." – Bob Hanlon Nov 30 '17 at 13:39
  • 1
    @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 ... – user1066 Nov 30 '17 at 13:59
  • 2
    @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. – jjc385 Nov 30 '17 at 14:08
  • Btw, Big +1, because I use Apply all the time and never knew it had this effect on symbols. – jjc385 Nov 30 '17 at 14:09
  • @jjc385 I think you are right, that explains a lot. Thanks! – user1066 Nov 30 '17 at 15:30
2

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

andre314
  • 18,474
  • 1
  • 36
  • 69
2
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}}
OkkesDulgerci
  • 10,716
  • 1
  • 19
  • 38
1

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}}]
Ulrich Neumann
  • 53,729
  • 2
  • 23
  • 55