As most regular users, I have developed utility functions complementing the Wolfram language for frequent tasks.
In particular, I have variations on Cases
(see example definitions below).
But I have trouble to add to them the pattern transformation capabilities of Case, such as Cases[ {1,3,5,6}, a:_Integer?EvenQ :> a/2 /; (a>0)]
because my current versions rely on Position, not on Cases. I usually can do what I want with my CaseMap function or other classical means at the expense of legibility and maintainability but I am also curious of the right way to construct such a pattern handling syntax.
CaseSort sorts specific elements disseminated in a structure
CaseSort[k_List, p_] := CaseSort[k, p, 1]
CaseSort[k_List, p_, z__] := Module[{kb = k, csz}, MapThread[
(Part[kb, Sequence @@ #2] = #1 ) &, {Sort[
Extract[k, csz = Position[k, p, z]]], csz}]; kb]
CaseSortBy is a straightforward variation on it
CaseSortBy[k_List, f_, p_] := CaseSortBy[k, f, p, 1]
CaseSortBy[k_List, f_, p_, z__] := Module[{kb = k, csz}, MapThread[
(Part[kb, Sequence @@ #2] = #1 ) &, {SortBy[
Extract[k, csz = Position[k, p, z]], f], csz}]; kb]
CaseMap is a cousin of MapAt and Replace
CaseMap[f_, k_List, p_] := CaseMap[k, p, 1]
CaseMap[f_, k_List, p_, z__] := Module[{kb = k, csz}, MapThread[
(Part[kb, Sequence @@ #2] = f[#1] ) &, {Extract[k,
csz = Position[k, p, z]], csz}]; kb]
CaseMapIndexed allows to have the positional context of the element when modifying it.
CaseMapIndexed[f_, k_List, p_] := CaseMapIndexed[k, p, 1]
CaseMapIndexed[f_, k_List, p_, z__] := Module[{kb = k, csz}, MapThread[
(Part[kb, Sequence @@ #2] = f[#1, #2] ) &, {Extract[k,
csz = Position[k, p, z]], csz}]; kb]
CaseSort[list_List, r:(_Rule | _RuleDelayed)] := (* stuff *)
? $\endgroup$