3 Stimmen

Optimierung der Teileextraktion

Ich habe diese spezielle Funktion, um Teile einer Liste im Formular zu extrahieren: Give[list, elem] gibt den Teil von Liste die der Position von elem in einem globalen $Reference Variable (falls definiert). Ich verwende diese Funktion häufig in meinem Code, daher habe ich beschlossen, sie zu optimieren. Hier habe ich es geschafft, so weit zu kommen, aber ehrlich gesagt, ich habe keine Ahnung, wie ich weiterkommen kann.

ClearAll[Give, $Reference, set];

Give::noref = "No, non-list or empty $Reference was defined to refer to by Give.";
Give::noelem = "Element (or some of the elements in) `1` is is not part of the reference set `2`.";
Give::nodepth = "Give cannot return all the elements corresponding to `1` as the list only has depth `2`.";

give[list_, elem_List, ref_] := Flatten[Pick[list, ref, #] & /@ elem, 1];
give[list_, elem_, ref_] := First@Pick[list, ref, elem];

Options[Give] = {Reference :> $Reference}; (* RuleDelayed is necessary, for it is possible that $Reference changes between two subsequent Give calls, and without delaying its assignment, ref would use previous value of $Reference instead of actual one. *)
Give[list_List, elem___, opts___?OptionQ] := Module[{ref, pos},
   ref = Reference /. {opts} /. Options@Give;
   Which[
      Or[ref === {}, Head@ref =!= List], Message[Give::noref]; {},
      Complement[Union@Flatten@{elem}, ref] =!= {}, Message[Give::noelem, elem, ref]; {},
      Length@{elem} > Depth@list - 1, Message[Give::nodepth, {elem}, Depth@list]; {},
      True, Fold[give[#1, #2, ref] &, list, {elem}]
]];

In[106]:= $Reference = {"A", "B", "C"};
set = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};

Give[set, "B"](* return specified row *)
Out[108]= {4, 5, 6}

In[109]:= Give[set, "B", "A"] (* return entry at specified row & column *)
Out[109]= 4

In[110]:= Give[set, {"B", "A"}] (* return multiple rows *)
Out[110]= {{4, 5, 6}, {1, 2, 3}}

Ich habe mich entschlossen, eindeutige Signaturfunktionsaufrufe wegzulassen, da die Listenversion die Nicht-Listenversion aufrufen könnte, was bedeutet, dass die Fehlerbehandlung mehrfach durchgeführt werden muss (für jedes Element in der Liste). Leider kann die Fehlerbehandlung nicht weggelassen werden. Wenn die verbesserte Version robuster ist (z. B. mehr Dimensionen verarbeiten kann), ist das kein Problem, aber die obigen Beispiele reichen aus.

In[139]:= First@Timing[Give[set, RandomChoice[$Reference, 10000]]] (* 1D test *)

Out[139]= 0.031

In[138]:= First@Timing[Table[Give[set, Sequence @@ RandomChoice[$Reference, 2]], {10000}]] (* 2d test *)

Out[138]= 0.499

Ich bin sicher, dass dies kein effizienter Code ist, also können Sie ihn gerne verbessern. Jede Hilfe ist willkommen, auch wenn sie nur ein paar Nanosekunden einspart.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X