2
$\begingroup$

Consider the following two tables:

tab1 = RandomReal[{1, 2}, {10, 4}];
tab2 = RandomReal[{2, 3}, {10, 6}];

and "charges" each representing the corresponding two columns of the tables:

qvalsTab1 = (1 - RandomInteger[{0, 2}, Length[Transpose[tab1]]/2]);
qvalsTab2 = (1 - RandomInteger[{0, 2}, Length[Transpose[tab2]]/2]);

(i.e., qvalsTab1[[1]] represents the first two columns of tab1, and so on).

I would like to join distinct pairs of columns from both tab1 and tab2 with either opposite values of qval or if both of qval are zero, and then join the resulting tables. My dumb code looks as follows:

vals = {};
Do[vals = 
  Join[vals, 
   If[qvalsTab1[[i]]*qvalsTab2[[j]] == -1 || (qvalsTab1[[i]] == 0 && 
       qvalsTab2[[j]] == 0), 
    Join[tab1[[All, i*{1, 2}]], tab2[[All, j*{1, 2}]], 2], {}]], {i, 
  1, Length[qvalsTab1]}, {j, 1, Length[qvalsTab2], 1}]
Do[vals = 
  Join[vals, 
   If[qvalsTab1[[i]]*
       qvalsTab1[[j]] == -1 || (qvalsTab1[[i]] == 0 && 
        qvalsTab1[[j]] == 0) && i != j, 
    Join[tab1[[All, i*{1, 2}]], tab1[[All, j*{1, 2}]], 2], {}]], {i, 
  1, Length[qvalsTab1]}, {j, 1, Length[qvalsTab1]}]
Do[vals = 
  Join[vals, 
   If[qvalsTab2[[i]]*
       qvalsTab2[[j]] == -1 || (qvalsTab2[[i]] == 0 || 
        qvalsTab2[[j]] == 0) && i != j, 
    Join[tab2[[All, i*{1, 2}]], tab2[[All, j*{1, 2}]], 2], {}]], {i, 
  1, Length[qvalsTab2]}, {j, 1, Length[qvalsTab2]}]

May I please ask you whether there is a more elegant and faster solution (in reality, these tables are very long and the number of columns may be arbitrary) for this exercise?

$\endgroup$
4
  • 1
    $\begingroup$ So, the column-pairs aren't adjacent. You either select columns 1&2, or columns 2&4, or columns 3&6 and so forth. Is that correct? $\endgroup$
    – lericr
    Commented Apr 26, 2023 at 0:54
  • 1
    $\begingroup$ In the first Do, you're collecting columns from both tab1 and tab2, in the second they all come from tab1, and in the third they all come from tab2. Correct? I hope my questions aren't presumptuous, but this code is very difficult to understand, and I keep losing track of what's happening. Would it actually be possible to describe your intent in pictures or clear words? $\endgroup$
    – lericr
    Commented Apr 26, 2023 at 1:07
  • 1
    $\begingroup$ shouldn't (qvalsTab2[[i]] == 0|| qvalsTab 2[[j]] == 0) in the last Do[...] be (qvalsTab2[[i]] == 0 && qvalsTab2[[j]] == 0)? $\endgroup$
    – kglr
    Commented Apr 26, 2023 at 2:08
  • $\begingroup$ @lericr : yes, you are correct. Excuse me for the unclear code. $\endgroup$ Commented Apr 26, 2023 at 7:27

1 Answer 1

3
$\begingroup$
tabs = {tab1, tab2};

qvals = {qvalsTab1, qvalsTab2};

Note: Assuming it is a typo, I replaced (qvalsTab2[[i]] == 0|| qvalsTab 2[[j]] == 0) in the last Do[...] in OP's code with (qvalsTab2[[i]] == 0 && qvalsTab2[[j]] == 0) to get vals.

1. A slightly shorter version of OP's code using another layer in Do[...]:

ClearAll[h, g, f]

h[qv_][k_, i_, j_] := MapThread[qv[[##]] &] @ {k, {i, j}}

g[t_][k_, i_, j_] := ## & @@ MapThread[t[[#, All, {1, 2} #2]] &] @ {k, {i, j}}

f = Module[{res = {}, l = Length /@ #2},
    Do[Module[{hv = h[#2][k, i, j], gv = Join[g[#][k, i, j], 2]},
      res = Join[res, If[Times @@ hv == -1 || (And @@ Thread[hv == 0] && 
              Or[Unequal @@ k, i != j]), gv, {}]]],
     {k, {{1, 2}, {1, 1}, {2, 2}}},
     {i, 1, l[[First @ k]]},
     {j, 1, l[[Last @ k]]}]; 
    res] &;

 f[tabs, qvals] == vals
True

2. An alternative approach:

ClearAll[selectIndices, joinColumns, combine]

selectIndices[vl_, neq_] := Select[Or[neq, Unequal @@ #] &&
     MatchQ[Sign@MapThread[vl[[##]] &]@{{1, 2}, #}, 
      {0, 0} | {1, -1} | {-1, 1}] &] @ Tuples[Range[Length /@ vl]]

joinColumns[t_] := Join[##,2]&@@MapThread[t[[#, All, {1, 2} #2]] &]@{{1, 2}, #} &

combine[tbs_, qvls_] := Apply[Join] @*
 Map[Join @@ Map[joinColumns@tbs[[#]]] @ selectIndices[qvls[[#]], Unequal@@#]&]


combine[tabs, qvals] @ {{1, 2}, {1, 1}, {2, 2}} == vals
True
$\endgroup$

Your Answer

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

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