1
|
9008 Views
|
10 Replies
|
17 Total Likes
View groups...
Share
GROUPS:

# Deleting a subset of elements from a set

Posted 11 years ago
 Given two lists, for exampledata = {"cat", "dog", "cat", "bird", "bird", "fish"};sub = {"cat", "fish"};I would like to have the following actionDeleteSubset[data_, sub_] := DeleteCases[data, x_ /; MemberQ[sub, x]]In[1]:= DeleteSubset[data, sub]Out[1]= {"dog", "bird", "bird"}Are there other ways to do this?
10 Replies
Sort By:
Posted 11 years ago
 Chad, I am assuming that the result you desire is {"dog", "cat", "bird", "bird"}In[1]:= Fold[DeleteCases[#1, #2, {1}, 1] &, data, sub]Out[1]= {"dog", "cat", "bird", "bird"}and putting another cat in the "sub" list we getdata = {"cat", "dog", "cat", "bird", "bird", "fish"};sub = {"cat", "cat", "fish"};In[2]:= Fold[DeleteCases[#1, #2, {1}, 1] &, data, sub]Out[2]= {"dog", "bird", "bird"}
Posted 11 years ago
 In[1]:= data /. Thread[sub -> Sequence[]]Out[1]= {"dog", "bird", "bird"}
Posted 11 years ago
 We have this same question in SE.See this link.
Posted 11 years ago
 Chad, here is a very crude attempt (choosing to remove "cat" in order of occurrence) ReplacePart[data, Thread[Map[Take[Position[data, #], Min[Count[sub, #], Count[data, #]]] &, sub] -> Sequence[]]](* Out[5]= {"dog", "cat", "bird", "bird"} *)
Posted 11 years ago
 Is there also a simple way to verify the number of elements in each list?Using Vitaly's list above, I would want the function to return {"cat",  'dog", "bird", "bird"}because only one "cat" is present in sub.
Posted 11 years ago
 data /. (# -> Sequence[] & /@ sub)is another option, and is slightly faster is you use it many many times. If you have many many items in 'sub' it might be an idea to create a dispatch table using Dispatch to speed it up even more.to give you a run down of the options:data={"cat","dog","cat","bird","bird","fish"};sub={"cat","fish"};AbsoluteTiming[Do[DeleteCases[data,x_/;MemberQ[sub,x]],{10^5}];]AbsoluteTiming[Do[DeleteCases[data,Alternatives@@sub],{10^5}];]AbsoluteTiming[Do[Select[data,FreeQ[#,Alternatives@@sub]&],{10^5}];]rules=(#->Sequence[]&/@sub);AbsoluteTiming[Do[data/.rules,{10^5}];]giving:{0.995983,Null}{0.279152,Null}{1.359880,Null}{0.192315,Null}Regards,Sander
Posted 11 years ago
 Select[data, FreeQ[#, Alternatives @@ sub] &]
Posted 11 years ago
 DeleteSubset[data_, sub_] := DeleteCases[data, Alternatives @@ sub]In[1]:= DeleteSubset[data, sub]Out[1]= {"dog", "bird", "bird"}
Posted 11 years ago
 Sander, I thought of that but this does not work in the same way - it gives a different result. Complement will delete all repeated elements. For this particular case you get a one "bird" while original functions preserves two of them.In[1]:= Complement[data, sub]Out[1]= {"bird", "dog"}Compare toIn[2]:= DeleteSubset[data, sub]Out[2]= {"dog", "bird", "bird"}It also rearranges elements. I basically would like structure of non-deleted elements to be the same.
Posted 11 years ago
 Complement[data,sub]Look also at the 'neighbour' function Union and Intersect.