4
$\begingroup$

I have two lists.

l1={
    {"Mn", "Mn1", 1., "B", 1.4}, 
    {"Al", "Al1", 1., "B", 1.4}
   };

l2={
   {{1, 1, 0.}, {11, 11, 0.}},

   {{2, 2, 0.}, {22, 22, 0.}, {222, 222, 0.}}
   }

This is a short version of the lists. The two lists always have the same Length so that their level-1 elements have a one-to-one relation. However, the elements of l2 can have varying Length as shown here.

I'd like to generate a new list as follows.

l3=
{
    {"Mn", "Mn1", {1, 1, 0.}, 1., "B", 1.4},
    {"Mn", "Mn1", {11, 11, 0.}, 1., "B", 1.4},

    {"Al", "Al1", {2, 2, 0.}, 1., "B", 1.4},
    {"Al", "Al1", {22, 22, 0.}, 1., "B", 1.4},
    {"Al", "Al1", {222, 222, 0.}, 1., "B", 1.4}
}

I think MapThread might be the direction to go, but I cannot think of any function to obtain the result. I'm not stick to MapThread. Any function that can do the job is okay as long as it's a vertorization method since that's what MMA favors.

Thank you.

$\endgroup$
  • $\begingroup$ Can you elaborate your receipt for l3 in detail? I understand nothing. BTW, the notation "l" is not good: compare with "I" and "1". $\endgroup$ – user64494 Jun 9 at 19:51
  • $\begingroup$ @user64494, it's really difficult for me to think of a good way to describe the format of l3 for English isn't my first language. That's why I use newlines to separate elements of l1 and l2 and change values of l2 to 1,11 and 2, 22, 222 for clarity. Maybe you could help me with that. But I think the answers provided understood my need and returns the desired format of l3. Also, I appreciate the suggestions of l1/2/3 may not be a good variable name. Thanks. $\endgroup$ – Bemtevi77 Jun 9 at 22:40
5
$\begingroup$

Yes you can use MapThread:

l3 = Join @@ MapThread[Function[{x, y}, Insert[x, #, 3] & /@ y], {l1, l2}]

Here's a more esoteric version that builds lists of mapping operators from l2 and then applies them to the elements of l1:

l3 = Join @@ MapThread[Through[#1[#2]] &, {Map[Insert[#, 3] &, l2, {2}], l1}]

See here for a discussion of the Through[#1[#2]]& operator.

$\endgroup$
  • $\begingroup$ A good code is a commented code. Comments are useful to both readers and authors. $\endgroup$ – user64494 Jun 9 at 19:52
  • 4
    $\begingroup$ @user64494 I expect some effort from the reader: the analysis and exegesis of other people's code snippets is a great learning tool. Give a man a fish and you feed him for a day; teach a man to fish and you feed him for a lifetime. $\endgroup$ – Roman Jun 9 at 20:32
  • $\begingroup$ @Roman, I like the 1st solution you provided because that's what I can remember in brain once I learn it. I was struggling with Part, but yours enlightened me. I'll need to understand better the Through approach. First time I heard of this function. Thanks. $\endgroup$ – Bemtevi77 Jun 9 at 22:12
5
$\begingroup$

You can also MapThread the function Thread[Insert[#, #2, 3]] & on the pair of lists {l1,l2}:

Join @@ MapThread[Thread[Insert[#, #2, 3]] &, {l1, l2}]

{{Mn, Mn1, {1, 1, 0.}, 1., B, 1.4}, {Mn, Mn1, {11, 11, 0.}, 1., B, 1.4},
{Al, Al1, {2, 2, 0.}, 1., B, 1.4}, {Al, Al1, {22, 22, 0.}, 1., B, 1.4}, {Al, Al1, {222, 222, 0.}, 1., B, 1.4}}

Alternatively, use the MapThread/Thread combination to create pairings appended with 3 and apply Insert to the resulting triples:

Join @@ Apply[Insert, 
  MapThread[Thread[{##, 3}, List, {2}] &, {l1, l2}], 
 {2}]

same result

$\endgroup$
  • 1
    $\begingroup$ Yes that's what I was looking for! Thanks. Prefix it with Join@@ to match the spec. $\endgroup$ – Roman Jun 9 at 21:05
  • $\begingroup$ @kglr, I never think of using Thread function before reading your answer. It's a little bit difficult for me to appreciate the mechanism of Thread. It's written "threads" f over any lists that appear in args in MMA's help page. But elements of l1 and l2 are both lists. I think Insert plays a role here so that the function only threads over element of l2. Am I understanding correctly? Thanks $\endgroup$ – Bemtevi77 Jun 9 at 22:19
  • $\begingroup$ @Yaofeng, you are right for the first one. In the second, the second and third arguments of Thread controls what to thread over and in which positions. $\endgroup$ – kglr Jun 9 at 22:37
  • $\begingroup$ @kglr, I compared the AbsoluteTiming for your Thread solution and Roman's Function solution. Yours is faster. Although it's not intuitive for me at the moment, but I guess that's the direction for me to go, in line with MMA's vectorization. Thanks again! $\endgroup$ – Bemtevi77 Jun 9 at 22:48
  • $\begingroup$ Although I think your Thread[Insert[##,3]] method is the most poetic, it's also the most brittle: Inserting first and Threading second makes the assumption that none of the elements of the lists in l1 are themselves lists. Example: with l1 = {{"Mn", {"Mn1"}, 1., "B", 1.4}, {"Al", "Al1", 1., "B", 1.4}} this method throws a Thread::tdlen. To be more robust it's probably advisable to Thread first and Insert second, as in your second method. $\endgroup$ – Roman Jun 10 at 7:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.