4
$\begingroup$

Consider a data list data, and a rule list rule. I want to select from data all elements that are in rule. For example, with

data = {a, a + 1, b, b + 2, c, c + 3, a + d, a + c, b + c};
rule = {a, d};

I want to select from data all elements that contains a or d. My solution is to invert the result from FreeQ, go through the rule list, and the pick out the results, like this:

HasQL[expr_, lst_] := 
 AnyTrue[Table[Not[FreeQ[expr, lst[[i]]]], {i, 1, Length[lst]}], 
  TrueQ]

and then Select[data, HasQL[#, rule] &] returns the expected result:

{a, 1 + a, a + d, a + c}

I tried cleaning up the code above:

HasQL[d_, r_] := AnyTrue[(!FreeQ[d, #]) & /@ r, TrueQ]
Select[data, HasQL[#, rule] &]

Is there a more elegant/clean way to achieve the same result?

$\endgroup$
2
  • 2
    $\begingroup$ Select[data, ! FreeQ[#, Alternatives @@ rule] &]? $\endgroup$ Mar 6, 2018 at 3:26
  • $\begingroup$ @J.M. Nice. Thanks a lot! $\endgroup$ Mar 6, 2018 at 3:33

4 Answers 4

3
$\begingroup$
data = {a, a + 1, b, b + 2, c, c + 3, a + d, a + c, b + c};

rule = {a, d};

Pre-compute p for better readability

p = Alternatives @@ rule;

Using Pick

Pick[data, Not @* FreeQ[p] /@ data]

{a, 1 + a, a + d, a c}

Using Cases

Cases[Plus[p, _] | p] @ data

{a, 1 + a, a + d, a + c}

A generalization (replacing a + c with a * c)

data = {a, a + 1, b, b + 2, c, c + 3, a + d, a * c, b + c};

Cases[_[OrderlessPatternSequence[p, _]] | p] @ data

{a, 1 + a, a + d, a c}

$\endgroup$
2
$\begingroup$
data = {a, a + 1, b, b + 2, c, c + 3, a + d, a + c, b + c};
rule = {a, d};

Select[data, Not@*FreeQ[Alternatives @@ rule]] 

DeleteCases[_?(FreeQ[Alternatives @@ rule])][data]

Extract[data, 
 List /@ First /@ 
   Position[data, Alternatives @@ rule, {1, ∞}]]

StringContainsQ [Alternatives @@ ToString /@ rule] /@ 
  ToString /@ data // Pick[data, #] &

Result:

{a, 1 + a, a + d, a + c}

$\endgroup$
2
$\begingroup$
data = {a, a + 1, b, b + 2, c, c + 3, a + d, a + c, b + c};

rule = {a, d};

Using AssociationThread and Lookup:

p = Alternatives @@ rule;

pos = Union@Cases[{a_} | {a_, _} :> a]@Position[data, p];

Lookup[AssociationThread[Range@Length@#, #] &@data, pos]

(*{a, 1 + a, a + d, a + c}*)
$\endgroup$
2
$\begingroup$

Using MemberQ:

l = {a, a + 1, b, b + 2, c, c + 3, a + d, a + c, b + c} ;
p = Alternatives @@ {a, d} ;
Select[l, MemberQ[#, p, All] &]

(* {a, 1 + a, a + d, a + c} *)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.