'Good' or 'Proper' Mathematica coding habits question
- To: mathgroup at smc.vnet.net
- Subject: [mg62028] 'Good' or 'Proper' Mathematica coding habits question
- From: "Matt" <anonmous69 at netscape.net>
- Date: Wed, 9 Nov 2005 03:46:04 -0500 (EST)
- Sender: owner-wri-mathgroup at wolfram.com
Hello, Due to the great help I've received from here, I've made limited progress with Mathematica. As I continue my journey, I am trying to adopt the philosophy: "When working with Mathematica, shy away from your long-learned habits of using loops, and instead try a functional or rule-based approach." To this end, I have coded up a few functions, which I'd appreciate any feedback on, as to whether I'm breaking an inviolate rule of Mathematica, or I'm using an egregious memory model, I'm duplicating some functionality that already exists in Mathematica proper, etc. Please bear in mind that I am by training and thought process an assembly and C/C++ developer that worries about details such as whether to use post-increment or post-increment when dealing with objects due to the unnecessary construction of temporary objects on the stack. I want to learn good Mathematica habits from the get-go. Here are the functions with short explanations for each: Cell[TextData[{ "extractNthElementFromEachSublistOfList takes as its first argument \ a list of lists, e.g. of the form {{", Cell[BoxData[ FormBox[ SubscriptBox["l", "x"], TraditionalForm]]], ", ", Cell[BoxData[ FormBox[ SubscriptBox["l", "y"], TraditionalForm]]], "}, {", Cell[BoxData[ FormBox[ SubscriptBox["l", "x"], TraditionalForm]]], ", ", Cell[BoxData[ FormBox[ SubscriptBox["l", "y"], TraditionalForm]]], "}, {", Cell[BoxData[ FormBox[ SubscriptBox["l", "x"], TraditionalForm]]], ", ", Cell[BoxData[ FormBox[ SubscriptBox["l", "y"], TraditionalForm]]], "}, {", Cell[BoxData[ FormBox[ SubscriptBox["l", "x"], TraditionalForm]]], ", ", Cell[BoxData[ FormBox[ SubscriptBox["l", "y"], TraditionalForm]]], "}} where each x and y subscript could denote any positive integer \ values to select from the set defined by 'l', and where 'l' could be \ an atomic object, or it could be itself an object with a head of List \ and an integer that specifies which element from each sublist to add \ to a list. This function will extract the nth element from each \ sublist of the input list and place it into a list and then return \ the flattened version of that list" }], "Text"] Cell[BoxData[{ RowBox[{ RowBox[{"Clear", "[", RowBox[{ "extractNthElementFromEachSublistOfList", ",", "testRun"}], "]"}], ";"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"extractNthElementFromEachSublistOfList", "[", RowBox[{"x_List", ",", "index_Integer", ",", RowBox[{"debugOn", ":", RowBox[{ RowBox[{"(", RowBox[{"_", "?", RowBox[{"(", RowBox[{ RowBox[{ "#", " ", "\[Element]", " ", "Booleans"}], " ", "&"}], ")"}]}], ")"}], ":", "False"}]}]}], "]"}], " ", ":=", " ", RowBox[{"Module", "[", "\[IndentingNewLine]", RowBox[{ RowBox[{"{", RowBox[{ RowBox[{"tempList", " ", "=", " ", RowBox[{"{", "}"}]}], ",", "error", ",", RowBox[{"noError", "=", "True"}], ",", "ret"}], "}"}], ",", "\[IndentingNewLine]", RowBox[{ RowBox[{"If", "[", RowBox[{ RowBox[{"debugOn", " ", "\[Equal]", " ", "True"}], ",", "\[IndentingNewLine]", RowBox[{"error", "=", RowBox[{"Catch", "[", RowBox[{ RowBox[{ RowBox[{"(", RowBox[{ RowBox[{"If", "[", RowBox[{ RowBox[{"(", RowBox[{ RowBox[{"bool", " ", "=", " ", RowBox[{ RowBox[{ "Length", "[", "#", "]"}], " ", "<", " ", RowBox[{ "Abs", "[", "index", "]"}]}]}], ";", RowBox[{"Print", "[", RowBox[{ "\"\<bool = \>\"", ",", "bool"}], "]"}], ";", "bool"}], ")"}], ",", RowBox[{ RowBox[{"noError", "=", "False"}], ";", RowBox[{ "Throw", "[", "#", "]"}]}]}], "]"}], ";", RowBox[{"tempList", " ", "=", " ", RowBox[{"{", RowBox[{"tempList", ",", RowBox[{"#", "[", RowBox[{"[", "index", "]"}], "]"}]}], "}"}]}]}], ")"}], " ", "&"}], " ", "/@", " ", "x"}], "]"}]}], ",", "\[IndentingNewLine]", RowBox[{"error", "=", "\[IndentingNewLine]", RowBox[{"Catch", "[", RowBox[{ RowBox[{ RowBox[{"(", RowBox[{ RowBox[{"If", "[", RowBox[{ RowBox[{ RowBox[{"Length", "[", "#", "]"}], " ", "<", " ", RowBox[{ "Abs", "[", "index", "]"}]}], ",", RowBox[{ RowBox[{"noError", "=", "False"}], ";", RowBox[{ "Throw", "[", "#", "]"}]}]}], "]"}], ";", RowBox[{"tempList", " ", "=", " ", RowBox[{"{", RowBox[{"tempList", ",", RowBox[{"#", "[", RowBox[{"[", "index", "]"}], "]"}]}], "}"}]}]}], ")"}], " ", "&"}], " ", "/@", " ", "x"}], "]"}]}]}], "\[IndentingNewLine]", "]"}], ";", "\[IndentingNewLine]", RowBox[{"If", "[", RowBox[{ RowBox[{"noError", "\[Equal]", "False"}], ",", "\[IndentingNewLine]", RowBox[{"ret", " ", "=", " ", RowBox[{"\"\<An index of \>\"", "<>", " ", RowBox[{"ToString", "[", "index", "]"}], "<>", "\"\< is out of bounds for sublist \>\"", "<>", RowBox[{"ToString", "[", "error", "]"}]}]}], ",", "\[IndentingNewLine]", RowBox[{"ret", " ", "=", RowBox[{"Flatten", "[", "tempList", "]"}]}]}], "]"}], ";", "\[IndentingNewLine]", "ret"}]}], "\[IndentingNewLine]", "]"}]}], ";"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"testRun", "[", RowBox[{"debugOn", ":", RowBox[{ RowBox[{"(", RowBox[{"_", "?", RowBox[{"(", RowBox[{ RowBox[{ "#", " ", "\[Element]", " ", "Booleans"}], " ", "&"}], ")"}]}], ")"}], ":", "False"}]}], "]"}], ":=", RowBox[{"Module", "[", RowBox[{ RowBox[{"{", RowBox[{ RowBox[{"testList", " ", "=", " ", RowBox[{"{", RowBox[{ RowBox[{"{", RowBox[{"1", ",", "2"}], "}"}], ",", " ", RowBox[{"{", RowBox[{"1", ",", "3"}], "}"}], ",", " ", RowBox[{"{", RowBox[{"1", ",", "4"}], "}"}], ",", " ", RowBox[{"{", RowBox[{"1", ",", "5"}], "}"}], ",", " ", RowBox[{"{", RowBox[{"1", ",", "6"}], "}"}]}], "}"}]}], ",", RowBox[{"unaryList", "=", RowBox[{"{", RowBox[{ "1", ",", "2", ",", "3", ",", "4", ",", "5", ",", "6"}], "}"}]}]}], "}"}], ",", "\[IndentingNewLine]", RowBox[{ RowBox[{"Print", "[", RowBox[{ "extractNthElementFromEachSublistOfList", "[", RowBox[{"testList", ",", "1", ",", "debugOn"}], "]"}], "]"}], ";", "\[IndentingNewLine]", RowBox[{"Print", "[", RowBox[{ "extractNthElementFromEachSublistOfList", "[", RowBox[{"testList", ",", RowBox[{"-", "2"}], ",", "debugOn"}], "]"}], "]"}], ";", RowBox[{"(*", RowBox[{ "this", " ", "is", " ", "equivalent", " ", "to", " ", "using", " ", "an", " ", "index", " ", RowBox[{"of", " ", "'"}], RowBox[{"1", "'"}]}], "*)"}], "\[IndentingNewLine]", RowBox[{"Print", "[", RowBox[{ "extractNthElementFromEachSublistOfList", "[", RowBox[{"testList", ",", "2", ",", "debugOn"}], "]"}], "]"}], ";"}]}], "\[IndentingNewLine]", "]"}]}], ";"}], "\[IndentingNewLine]", RowBox[{"testRun", "[", "]"}]}], "Input"] Cell["\<\ findLeastOrGreatest is used to find within a given list of lists the \ least or greatest value in a column dictated by pos. Whether the \ least or greatest is determined is controlled by an optional \ parameter, 'greaterThan', which if given explicitly as 'False' will \ find the least value.\ \>", "Text"] Cell[BoxData[{ RowBox[{ RowBox[{"Clear", "[", RowBox[{"findLeastOrGreatest", ",", "testRun"}], "]"}], ";"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"findLeastOrGreatest", "[", RowBox[{ RowBox[{"inList_List", "?", RowBox[{"(", RowBox[{ RowBox[{"(", RowBox[{ RowBox[{"Depth", "[", "#", "]"}], "\[Equal]", "3"}], ")"}], " ", "&"}], ")"}]}], ",", " ", RowBox[{"pos", ":", RowBox[{"(", RowBox[{"_Integer", "?", RowBox[{"(", RowBox[{ RowBox[{ RowBox[{"Positive", "[", "#", "]"}], " ", "&&", " ", RowBox[{"#", " ", "<", " ", "3"}]}], "&"}], ")"}]}], ")"}]}], ",", RowBox[{"greaterThan", ":", RowBox[{ RowBox[{"(", RowBox[{"_", "?", RowBox[{"(", RowBox[{ RowBox[{ "#", " ", "\[Element]", " ", "Booleans"}], " ", "&"}], ")"}]}], ")"}], ":", "True"}]}]}], "]"}], " ", ":=", " ", RowBox[{"Module", "[", RowBox[{ RowBox[{"{", RowBox[{"op", "=", "GreaterEqual"}], "}"}], ",", "\[IndentingNewLine]", RowBox[{ RowBox[{"If", "[", RowBox[{ RowBox[{ "False", " ", "\[Equal]", " ", "greaterThan"}], ",", RowBox[{"op", "=", "Less"}]}], "]"}], ";", "\[IndentingNewLine]", RowBox[{"IntegerPart", "[", RowBox[{ RowBox[{"Fold", "[", RowBox[{ RowBox[{ RowBox[{"If", "[", RowBox[{ RowBox[{"op", "[", RowBox[{ RowBox[{"#1", "[", RowBox[{"[", "pos", "]"}], "]"}], ",", " ", RowBox[{"#2", "[", RowBox[{"[", "pos", "]"}], "]"}]}], "]"}], ",", "#1", ",", "#2"}], "]"}], " ", "&"}], ",", RowBox[{"inList", "[", RowBox[{"[", "1", "]"}], "]"}], ",", "inList"}], "]"}], "[", RowBox[{"[", "pos", "]"}], "]"}], "]"}]}]}], "\[IndentingNewLine]", "]"}]}], ";"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"testRun", "[", "]"}], ":=", RowBox[{"Module", "[", RowBox[{ RowBox[{"{", RowBox[{"testList", " ", "=", " ", RowBox[{"{", RowBox[{ RowBox[{"{", RowBox[{"1", ",", "2"}], "}"}], ",", " ", RowBox[{"{", RowBox[{"1", ",", "3"}], "}"}], ",", " ", RowBox[{"{", RowBox[{"1", ",", "4"}], "}"}], ",", " ", RowBox[{"{", RowBox[{"1", ",", "5"}], "}"}], ",", " ", RowBox[{"{", RowBox[{"1", ",", "6"}], "}"}]}], "}"}]}], "}"}], ",", "\[IndentingNewLine]", RowBox[{ RowBox[{"Print", "[", RowBox[{"findLeastOrGreatest", "[", RowBox[{"testList", ",", "1"}], "]"}], "]"}], ";", "\[IndentingNewLine]", RowBox[{"Print", "[", RowBox[{"findLeastOrGreatest", "[", RowBox[{"testList", ",", "2", ",", "False"}], "]"}], "]"}], ";", "\[IndentingNewLine]", RowBox[{"Print", "[", RowBox[{"findLeastOrGreatest", "[", RowBox[{"testList", ",", "2"}], "]"}], "]"}], ";"}]}], "\[IndentingNewLine]", "]"}]}], ";"}], "\[IndentingNewLine]", RowBox[{"testRun", "[", "]"}]}], "Input"] Here is a table of 20 pairs of numbers. values = Table[{Random[Real, {-2, 2}] i, Random[Real, {-2,2}] i}, {i, 1, 20}]; I want to extract all elements from 'values' where each of the values of a particular element are negative. This was my first approach: negElems = {}; (If[Negative[#[[1]]] && Negative[#[[2]]], negElems = {negElems, #}]) & /@ values negElems Flatten[%] Partition[%, 2] I didn't like that approach particularly because it created a 'temporary' list with many Nulls embedded in it. So, then I tried a Fold approach: negElems = {}; Fold[If[Negative[#2[[1]]] && Negative[#2[[2]]], negElems = {negElems, #2}, negElems] &, values[[1]], values]; Flatten[%] Partition[%, 2] That seems 'nicer', but I'm sure there's even better and more efficient ways of doing this (or perhaps, what I've done is as bad as bad can be). All feedback is appreciated. Thanks, Matt
- Follow-Ups:
- Re: 'Good' or 'Proper' Mathematica coding habits question
- From: Igor Antonio <igora@wolf-ram.com>
- Re: 'Good' or 'Proper' Mathematica coding habits question
- From: "Carl K. Woll" <carl@woll2woll.com>
- Re: 'Good' or 'Proper' Mathematica coding habits question