Join
is quite clean I think:
lst1 = {{x1, y1}, {x2, y2}, {x3, y3}, {x4, y4}};
lst2 = {{x1, z1}, {x2, z2}, {x3, z3}, {x4, z4}};
{#, #*#4/#2} & @@@ Join[lst1, lst2, 2]
{{x1, (x1 z1)/y1}, {x2, (x2 z2)/y2}, {x3, (x3 z3)/y3}, {x4, (x4 z4)/y4}}
For more efficiency a Transpose
pair lets one operate by column enabling vector arithmetic on packed arrays:
{#, #*#4/#2}\[Transpose] & @@ (Join[lst1, lst2, 2]\[Transpose])
{{x1, (x1 z1)/y1}, {x2, (x2 z2)/y2}, {x3, (x3 z3)/y3}, {x4, (x4 z4)/y4}}
Timings with a large array of reals:
{lst1, lst2} = List @@ RandomReal[{1, 99}, {2, 500000, 2}];
{#, #*#4/#2} & @@@ Join[lst1, lst2, 2] // Timing // First
{#, #*#4/#2}\[Transpose] & @@ (Join[lst1, lst2, 2]\[Transpose]) // Timing // First
0.763
0.025
Shutao Tang's methods for comparison:
{#1, #1 #4/#2} & @@@ (Flatten[#, 1] & /@ Thread@{lst1, lst2}) // Timing // First
{#1, #1 #4/#2} & @@@ (Flatten[#, 1] & /@ Transpose[{lst1, lst2}]) //
Timing // First
Flatten[#, 1] & /@ Transpose[{lst1, lst2}] /. {x_, y_, x_, z_} :> {x, x z/y} //
Timing // First
Flatten[#, 1] & /@ Thread@{lst1, lst2} /. {x_, y_, x_, z_} :> {x, x z/y} //
Timing // First
MapThread[{First@#1, Times @@ #1/Last@#2} &, {lst1, lst2}] // Timing // First
1.13
0.831
0.687
0.982
1.42
Transpose[{list1[[All, 1]], Times @@@ list2/list1[[All, 2]]}]
$\endgroup$