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$
2
  • $\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
    Commented Jun 9, 2019 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$
    – user34223
    Commented Jun 9, 2019 at 22:40

2 Answers 2

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$
3
  • $\begingroup$ A good code is a commented code. Comments are useful to both readers and authors. $\endgroup$
    – user64494
    Commented Jun 9, 2019 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
    Commented Jun 9, 2019 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$
    – user34223
    Commented Jun 9, 2019 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$
6
  • 1
    $\begingroup$ Yes that's what I was looking for! Thanks. Prefix it with Join@@ to match the spec. $\endgroup$
    – Roman
    Commented Jun 9, 2019 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$
    – user34223
    Commented Jun 9, 2019 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
    Commented Jun 9, 2019 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$
    – user34223
    Commented Jun 9, 2019 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
    Commented Jun 10, 2019 at 7:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.