3
$\begingroup$

Please consider the following:

Split[data, patterns &]
patterns=Not[#=="a"]&&Not[#=="b"]&&...&&Not[#=="blabla"];

How can I define patterns without typing &&Not[#=="char"] for every single pattern?

$\endgroup$
5
$\begingroup$

You can add some syntactic sugar to do that relatively easily. For example, define a head for that:

ClearAll[SplitPattern];
SplitPattern /: Split[expr_, SplitPattern[pt_]] :=
   Split[expr, MatchQ[#, pt] &];

And use this as follows:

lst = {"a", "b", "c", "d", "blabla", "e", "f"}
Split[lst,SplitPattern[Except["a"|"b"|"blabla"]]]

(*  {{a},{b},{c,d,blabla},{e,f}} *)

The performance may not be that great, but I guess the question was more about convenience.

$\endgroup$
3
$\begingroup$

It looks like you really want to use set of different dividers, in that case, you can simply test using a function that checks whether the current element is a member of your set of deviders:

 dividers = {3, 4, 5}
 Split[Range@10, ! MemberQ[dividers, #] &]

To answer your litteral question, your patterns is basically And taken over a range of structurally identical terms that are functions of a list of dividers, so you could use Map and Apply

patterns= Function[t, And @@ (Not[t == #] & /@ {"a", "b", "blabla"})]

Then you can use

lst = {"a", "b", "c", "d", "blabla", "e", "f"}
Split[lst,patterns]
{{"a"}, {"b"}, {"c", "d", "blabla"}, {"e", "f"}}

In a similar fasion, if you just wanted to combine a seriues of different test you could use And@@{test1[#],test2[#],test3[#]}&.

I hope this helps.

$\endgroup$
  • $\begingroup$ I like your approach better from the perspective of comprehension. However, LeonidShifrins approach is faster. $\endgroup$ – John Dec 4 '12 at 16:33
  • $\begingroup$ @John One of the reasons why my code might be faster is that the patterns function here does not short-circuit: even when the very first pattern matches, it still goes on evaluating all others. $\endgroup$ – Leonid Shifrin Dec 4 '12 at 16:42
1
$\begingroup$

Another option is to create a temporary function which evaluates to False for your target strings and True otherwise.

splitAt[data_, x_] := Module[{f},
  (f[#, _] = False) & /@ x;
  f[__] = True;
  Split[data, f]]

lst = {"a", "b", "c", "d", "blabla", "e", "f"} ;
splitAt[lst, {"a", "b", "blabla"}]

(* {{"a"}, {"b"}, {"c", "d", "blabla"}, {"e", "f"}} *)
$\endgroup$

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.