"Mr Wizard Todd", Manfred Plagmann, and Sophia Scheibe have done Mathematica users a nice favor by getting permission from McGraw-Hill to distribute licensed copies of David Wagner' s superb book, Power Programming in Mathematica. (Dropbox link: https://www.dropbox.com/s/j2dsyvptnxjd369/Wagner%20All%20Parts-RC.pdf)
A related post is How to See the Equivalence of Select and Cases.
Here are some nice examples of predicates from Wagner (re - written in my Prefix/Postfix dialect).Test a list to see if all of its entries are odd integers.
allOdd@aList_List:=Length@Select[aList,OddQ]==Length@aList
allOdd@{2,3,5,6}
False
allOdd@{3,5,7,9}
True
This predicate tests a List to see if its parts are identical. Count returns all Parts that are Equal to the First Part.
identicalListPartsQ@aList_List:=Count[aList, First@aList] == Length@aList
identicalListPartsQ@{a,b,c,4}
False
identicalListPartsQ@{a,a,a,a}
True
SameQ vs. Equal and Testing for Lists
SubsetQ determines if its first argument is a subset of its second argument and returns True or False. Wagner's function did not include a List test and he notes on Equal vs.SameQ : "The use of === rather than == makes SubsetQ return False if either set1 or set2 is not a list. Try it with Equal."
I use the Head test: set1_List, which rejects a non-List argument before evaluation. And more importantly, SameQ should always be used to test non-numerical equivalence. In fact using Equal here can give screwy results in part because of its usage as the mathematical "equals" (=) in Mathematica's syntax for equations.
When using abbreviated operators, we should first determine their Precedence:
Precedence/@{Union,Equal,SameQ}
{300.,290.,290.}
Since Union is slightly stickier than SameQ, the Union will be performed before the SameQ test.
subsetQ[set1_,set2_]:=set1∪set2===set2
subsetQ[{a,b,c},{a,b,d}]
False
subsetQ[{a,b},{a,b,2}]
False
Union Sorts Its Result
Whoops! Wagner's function didn't work. Let's find out why:
subsetQ[{a,b},{a,b,2}]//Trace
{subsetQ[{a,b},{a,b,2}],{a,b}∪{a,b,2}==={a,b,2},{{a,b}∪{a,b,2},{2,a,b}},{2,a,b}==={a,b,2},False}
The fact that Union returns a sorted List fouls up the comparison. Let's try a fix with Sort:
Clear@subsetQ;subsetQ[set1_,set2_]:=set1∪set2===Sort@set2
And it works - you see in the last step Sort fixes the order.
subsetQ[{a,b},{a,b,2}]//Trace
{subsetQ[{a,b},{a,b,2}],{a,b}∪{a,b,2}===Sort[{a,b,2}],{{a,b}∪{a,b,2},{2,a,b}},{Sort[{a,b,2}],{2,a,b}},{2,a,b}==={2,a,b},True}
Greater (>) is a "non-Q" predicate so the last statement (lacking a return-suppressing semi-colon), returns True or False.
More on predicates: http://mathematica-guide.blogspot.com/2015/07/how-to-see-equivalence-of-select-and.html
A related post is How to See the Equivalence of Select and Cases.
Here are some nice examples of predicates from Wagner (re - written in my Prefix/Postfix dialect).Test a list to see if all of its entries are odd integers.
allOdd@aList_List:=Length@Select[aList,OddQ]==Length@aList
allOdd@{2,3,5,6}
False
allOdd@{3,5,7,9}
True
This predicate tests a List to see if its parts are identical. Count returns all Parts that are Equal to the First Part.
identicalListPartsQ@aList_List:=Count[aList, First@aList] == Length@aList
identicalListPartsQ@{a,b,c,4}
False
identicalListPartsQ@{a,a,a,a}
True
SameQ vs. Equal and Testing for Lists
SubsetQ determines if its first argument is a subset of its second argument and returns True or False. Wagner's function did not include a List test and he notes on Equal vs.SameQ : "The use of === rather than == makes SubsetQ return False if either set1 or set2 is not a list. Try it with Equal."
I use the Head test: set1_List, which rejects a non-List argument before evaluation. And more importantly, SameQ should always be used to test non-numerical equivalence. In fact using Equal here can give screwy results in part because of its usage as the mathematical "equals" (=) in Mathematica's syntax for equations.
When using abbreviated operators, we should first determine their Precedence:
Precedence/@{Union,Equal,SameQ}
{300.,290.,290.}
Since Union is slightly stickier than SameQ, the Union will be performed before the SameQ test.
subsetQ[set1_,set2_]:=set1∪set2===set2
subsetQ[{a,b,c},{a,b,d}]
False
subsetQ[{a,b},{a,b,2}]
False
Union Sorts Its Result
Whoops! Wagner's function didn't work. Let's find out why:
subsetQ[{a,b},{a,b,2}]//Trace
{subsetQ[{a,b},{a,b,2}],{a,b}∪{a,b,2}==={a,b,2},{{a,b}∪{a,b,2},{2,a,b}},{2,a,b}==={a,b,2},False}
The fact that Union returns a sorted List fouls up the comparison. Let's try a fix with Sort:
Clear@subsetQ;subsetQ[set1_,set2_]:=set1∪set2===Sort@set2
And it works - you see in the last step Sort fixes the order.
subsetQ[{a,b},{a,b,2}]//Trace
{subsetQ[{a,b},{a,b,2}],{a,b}∪{a,b,2}===Sort[{a,b,2}],{{a,b}∪{a,b,2},{2,a,b}},{Sort[{a,b,2}],{2,a,b}},{2,a,b}==={2,a,b},True}
Greater (>) is a "non-Q" predicate so the last statement (lacking a return-suppressing semi-colon), returns True or False.
More on predicates: http://mathematica-guide.blogspot.com/2015/07/how-to-see-equivalence-of-select-and.html
Very informative blog article.Really looking forward to read more. Great.
ReplyDelete