Advertisement
simonjtyler

List comprehension for Mathematica

Dec 10th, 2011
230
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.89 KB | None | 0 0
  1. (* http://stackoverflow.com/questions/6367932/generate-a-list-in-mathematica-with-a-conditional-tested-for-each-element/6368770#6368770 *)
  2.  
  3. (* The code *)
  4.  
  5. TableIf::usage = "TableIf[expr,{i,\!\(\*SubscriptBox[\(i\), \(max\)]\)},addif] will \
  6. generate a list of values expr when i runs from 1 to \
  7. \!\(\*SubscriptBox[\(i\), \(max\)]\), only including elements if \
  8. addif[expr] returns true. Note that addif can have dependence on the \
  9. iterator variables.
  10. The default of addif is True&.
  11. TableIf[expr,{\!\(\*SubscriptBox[\(i\), \(max\)]\)},addif] iterates \
  12. \!\(\*SubscriptBox[\(i\), \(max\)]\) times with no named index.
  13. TableIf[expr,{i,\!\(\*SubscriptBox[\(i\), \
  14. \(min\)]\),\!\(\*SubscriptBox[\(i\), \(max\)]\)},addif] starts with \
  15. i=\!\(\*SubscriptBox[\(i\), \(min\)]\).
  16. TableIf[expr,{i,\!\(\*SubscriptBox[\(i\), \
  17. \(min\)]\),\!\(\*SubscriptBox[\(i\), \(max\)]\),di},addif] uses steps di.
  18. TableIf[expr,{i,{\!\(\*SubscriptBox[\(i\), \
  19. \(1\)]\),\!\(\*SubscriptBox[\(i\), \(2\)]\),...}},addif] uses the \
  20. successive values \!\(\*SubscriptBox[\(i\), \(1\)]\), \
  21. \!\(\*SubscriptBox[\(i\), \(2\)]\), ....
  22. TableIf[expr,{i,\!\(\*SubscriptBox[\(i\), \
  23. \(max\)]\)},{j,\!\(\*SubscriptBox[\(j\), \(max\)]\)},addif], will \
  24. give a multidimensional list.";
  25.  
  26. Unprotect[TableIf]
  27. ClearAll[TableIf];
  28. SetAttributes[TableIf, HoldAll];
  29. SyntaxInformation[TableIf] = {"ArgumentsPattern" -> {_, {_, _., _., _.} .., _.},
  30. "LocalVariables" -> {"Table", {2, -2}}};
  31.  
  32. (* If not given a pure function for addif, then turn it into a function with trivial dependence on expr. *)
  33. (* This allows tests depending only on the iterators. *)
  34. (* Iterators must be lists. Can have any number of iterators. *)
  35. (* The test addif must match the pattern Except[_List] is so that it will never match an iterator. *)
  36.  
  37. TableIf[expr_, iter : {__} .., addif : Except[_List] : (True &)] :=
  38. Module[{indices, indexedRes, sowTag, Q},
  39. If[Head[addif] === Function || Head[addif] === CompiledFunction,
  40. Q = addif, Q = Function[{}, addif]];
  41. SetDelayed@@Prepend[Thread[Map[Take[#, 1] &, List @@ Hold @@@ Hold[iter]], Hold], indices];
  42. indexedRes = Last@Reap[Do[If[Q[#], Sow[{#, indices}, sowTag]] &[expr], iter], sowTag];
  43. indexedRes = If[# === {}, #, First@#]&@indexedRes;
  44. Map[First, SplitBy[indexedRes, Table[With[{i = i},
  45. Function[Slot[1][[2, i]]]], {i, Length[Hold[iter]] - 1}]], {-3}]]
  46.  
  47. (* Catch bad iterators, use General::itform *)
  48.  
  49. TableIf[expr_, iter__, addif : Except[_List] : (True &)] :=
  50. Module[{pos = First@Flatten@Position[{iter}, Except[{Repeated[_, 4]}], {1}, 1, Heads -> False]},
  51. Message[TableIf::itform, Extract[{iter}, pos], pos + 1];
  52. HoldForm[TableIf[expr, iter, addif]]]
  53.  
  54. SetAttributes[TableIf, ReadProtected];
  55. Protect[TableIf];
  56.  
  57. (* Some test code *)
  58. i = x;
  59. TableIf[i^j, {i, 8}, {j, 8}, Mod[i, 4] == Mod[j, 4] && 50 < # < 1000 &]
  60. TableIf[f[i, j], {i, 5}, {j, 5}, (i == 4 || i == 1) && j < 3]
  61.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement