1
$\begingroup$

There is 4 lists, 3 of them are at same length (l0, l1 and l3).

l0={2,3,4,2,5};
l1={{1,2},{2,4},{3,1},{4,3},{5,1}};
l2={{1,2},{1,3},{2,1},{3,1},{4,5},{5,4}};
l3={0,0,0,0,0};

Each member of l0 should be comparison with second element of corresponding member of l1, if it was greater we call them Beep members.(here third and fifth member of l0), then from l2 we choose members that have equal value at first element with Beep (first element) and call them Ops. At last add one to each element of l3 at position Ops[[2]] .

here: Beep: {3,1} and {5,1}, Ops: {3,1} and {5,4} and finally l3={1,0,0,1,0}.

I write a function that do this, Is it best way for doing this?

Func[l0_] := 
  Module[{l3 = ConstantArray[0, n]}, 
   MapThread[
     If[#1 > #2[[2]], ++l3[[
         Cases[l2, {x_, y_} /; x == #2[[1]] :> y]]]] &, {l0, l1}];
   ];

How to Compile it?

$\endgroup$
  • 2
    $\begingroup$ l3[[#]] ++ & /@ Last /@ Cases[ l2, {Alternatives @@ (First /@ Pick[l1, Thread[l0 > Last /@ l1]]), _}] $\endgroup$ – Dr. belisarius Jan 16 '16 at 5:53
  • $\begingroup$ Is the length of sublists of l1 and l2 always 2? $\endgroup$ – xzczd Jan 16 '16 at 7:09
  • $\begingroup$ Thanks, @Dr.belisarius, But how can do it in compile? $\endgroup$ – jack cilba Jan 16 '16 at 8:07
  • $\begingroup$ @xzczd yes, always. And first element of each member of l1 is their position. $\endgroup$ – jack cilba Jan 16 '16 at 8:09
6
$\begingroup$

Your Func is far beyond best. As mentioned before, currently you'd better set effort on learning to code in "Mathematica-style" rather than try to relieve the slowness (which is mostly caused by bad coding in my view) with Compile. Here's an uncompiled function that's about 300 times faster than your Func:

func = Function[{l0, l1, l2, ll3}, Module[{l3 = ll3, beep, oops},
    beep = First@Transpose@Pick[l1, UnitStep[Last@Transpose@l1 - l0], 0]; 
    oops = Pick[Last@Transpose@l2, First@Transpose@l2, #] & /@ beep // Flatten; 
    l3[[#]]++&/@oops; l3]];

n = 10^4;
l0 = RandomInteger[{1, n}, n];
l1 = Transpose[{Range@n, RandomInteger[{1, n}, n]}];
l2 = RandomInteger[{1, n}, {n, 2}];
l3 = ConstantArray[0, Length@l0];

rst1 = func[l0, l1, l2, l3]; // AbsoluteTiming
(* {0.385027, Null} *)

Func[l0]; // AbsoluteTiming
(* {125.067177, Null} *)

If you still insist on learning the usage of Compile, I suggest you to start from here, and if speed is really really concerned, here's the fastest approach I found so far:

cf2 = ReleaseHold@
  With[{g = Compile`GetElement}, 
   Hold@Compile[{{l0, _Integer, 1}, {l1, _Integer, 2}, {l2, _Integer, 2}, {ll3, _Integer,
          1}}, Module[{l3 = ll3, n = Length@l0, m = Length@l2, index}, 
        Do[If[l0[[i]] > l1[[i, 2]], 
          Do[If[l2[[j, 1]] == l1[[i, 1]], ++l3[[l2[[j, 2]]]]], {j, m}]], {i, n}]; l3], 
       CompilationTarget -> "C", RuntimeOptions -> "Speed"] //. 
     HoldPattern[Part[b__]] :> g[b] //. HoldPattern[++g[b__]] :> ++Part[b]]

rst2 = cf2[l0, l1, l2, l3]; // AbsoluteTiming
(* {0.053404, Null} *)
rst1 == rst2
(* True *)

Notice a C compiler should be installed on your computer.

| improve this answer | |
$\endgroup$
  • $\begingroup$ Yep. A better advice than mine anyway $\endgroup$ – Dr. belisarius Jan 16 '16 at 10:59

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.