Generate certain list from two lists

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.

• Can you elaborate your receipt for l3 in detail? I understand nothing. BTW, the notation "l" is not good: compare with "I" and "1". – user64494 Jun 9 '19 at 19:51
• @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. – Bemtevi77 Jun 9 '19 at 22:40

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.

• A good code is a commented code. Comments are useful to both readers and authors. – user64494 Jun 9 '19 at 19:52
• @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. – Roman Jun 9 '19 at 20:32
• @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. – Bemtevi77 Jun 9 '19 at 22:12

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,

• Yes that's what I was looking for! Thanks. Prefix it with Join@@ to match the spec. – Roman Jun 9 '19 at 21:05
• @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 – Bemtevi77 Jun 9 '19 at 22:19
• @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. – kglr Jun 9 '19 at 22:37
• @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! – Bemtevi77 Jun 9 '19 at 22:48
• 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. – Roman Jun 10 '19 at 7:55