1
$\begingroup$

Please can anyone help ? I have a list of sets, and I am trying to find the positions in that list of those sets which are subsets of a given set. (Here I am ignoring the distinction between lists and sets, possibly at my peril.)

The following code

subsetQ[A_, B_] := Intersection[A, B] == A;
Position[{{a, b}, {b}, {e, f}, {c, e}, {c}}, _?(subsetQ[#, {b, c, e}] &), 1]

gives the output

{{2}, {4}, {5}}

which is exactly what I want.

Many thanks to these contributors

How to find the position of elements in a list satisfying criteria

for showing me the way. However, my code also generates the error message

Intersection::normal: "Nonatomic expression expected at position 1 in List[Intersection]{b,c,e}."

Is there a way to avoid this message, other than suppressing it using

Off[General::normal].

?

I have studied the documentation here:

http://reference.wolfram.com/language/tutorial/PuttingConstraintsOnPatterns.html

to try to understand whether I should use x_/; or _?() but I confess I don't understand it well.

Thank you very much.

$\endgroup$

marked as duplicate by Mr.Wizard Sep 25 '15 at 14:01

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 1
    $\begingroup$ In my experience, _? is faster but is limited in that it requires something that can be applied as a pure function. /; isn't necessarily always slower and offers more flexibility in that you can follow it with any type of expression that returns a Boolean value. I'm curious why you didn't use the built-in SubsetQ? Are you on an older version? $\endgroup$ – IPoiler Sep 25 '15 at 13:49
  • $\begingroup$ Duplicates: (7688), (67100), (73323). Related: (17752) $\endgroup$ – Mr.Wizard Sep 25 '15 at 14:01
  • $\begingroup$ Thank you very much @Mr.Wizard, It's Pronounced Oiler, MarcoB and Adriano Pascoletti. Sorry about the duplicate question. Regarding SubsetQ, yes I am using version 9, so I had to make my own function ! $\endgroup$ – Simon Sep 25 '15 at 22:29
2
$\begingroup$

Specifying that your pattern should only match expressions with a List head prevents the error that you observed.

In addition, there already is a built-in SubsetQ function (here are its docs). I would typically try to use a built-in over a user function whenever possible, since the former might benefit from better algorithms and internal optimizations under the hood.

The syntax of the built in is slightly different from that of your function, but the idea is essentially the same. Here are two versions that achieve the same goal using either PatternTest (?) or Condition (/;):

Position[{{a, b}, {b}, {e, f}, {c, e}, {c}}, p_List /; SubsetQ[{b, c, e}, p], 1]
Position[{{a, b}, {b}, {e, f}, {c, e}, {c}}, _List?(SubsetQ[{b, c, e}, #] &), 1]

(* Out:
{{2}, {4}, {5}}
{{2}, {4}, {5}}
*)

Leonid Shifrin recently wrote up a deeper discussion of PatternTest vs. Condition that you might be interested as an answer to this question: Why does pattern test work only with pure functions?

$\endgroup$
2
$\begingroup$

Add the option Heads -> False:

Position[{{a, b}, {b}, {e, f}, {c, e}, {c}}, _?(subsetQ[#, {b, c, e}]&), 1, Heads->False]

(* Out: {{2}, {4}, {5}} *)
$\endgroup$

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