4
$\begingroup$

I want to make a selection on this list

words = {{{"word1", "word2"}, 19}, {{"word1", "word3"}, 
   8}, {{"word1", "word4"}, 7}, {{"word2", "word5"}, 
   7}, {{"word2", "word5"}, 7}, {{"word3", "word6"}, 
   7}, {{"word3", "word7"}, 7}, {{"word3", "word8"}, 
   6}, {{"word4", "word6"}, 6}};

From this list, I want to select all 'records' which have one of these words

wordsselect = {"word2", "word4", "word8"}

The desirde output is:

wordsnew = {{{"word1", "word2"}, 19}, {{"word1", "word4"}, 
   7}, {{"word2", "word5"}, 7}, {{"word2", "word5"}, 
   7}, {{"word3", "word8"}, 6}, {{"word4", "word6"}, 6}}

I tried to make a selection based on one word

Select[words[[All, {1, 2}]], MemberQ[#[[1]], "word2"] &]

this works fine. So I tried the next script

Select[words[[All, {1, 2}]], MemberQ[#[[1]], wordsselect ] &]

The output is empty {}

I have two questions:

  1. How do I get the desired output?

  2. Why is my second try not working?

$\endgroup$
1
  • 8
    $\begingroup$ Try Alternatives@@wordsselect instead. This will be a real pattern involving alternatives. Your pattern matches with any list that exactly equals the list of three words. $\endgroup$ Jul 13, 2015 at 20:59

8 Answers 8

6
$\begingroup$

As already noted the second argument of MemberQ needs to be a pattern or literal expression; Alternatives can be used here.

Another method is to use IntersectingQ instead:

Select[words, IntersectingQ[#[[1]], wordsselect] &]
{{{"word1", "word2"}, 19}, {{"word1", "word4"}, 7},
 {{"word2", "word5"}, 7}, {{"word2", "word5"}, 7},
 {{"word3", "word8"}, 6}, {{"word4", "word6"}, 6}}
$\endgroup$
1
  • $\begingroup$ thank you again finding yet another useful function I was not aware of: IntersectingQ...my blindspot seems ever increasing as my time is ever decreasing...+1 :) $\endgroup$
    – ubpdqn
    Jul 14, 2015 at 12:55
3
$\begingroup$
Select[words, MemberQ[#[[1]], "word1" | "word2" | "word8"] &]
$\endgroup$
3
$\begingroup$
  1. This one should work:

Select[words, Or @@ (MemberQ[wordsselect, #] & /@ #[[1]]) &]

It checks for each one of the words in the first list-element. If there is at least one word in the wordsselect list then the whole element is selected.

  1. With MemberQ[#[[1]], wordsselect ] & you are checking if the list wordsselect is inside each {"wordX","wordY"}
$\endgroup$
3
$\begingroup$

Just for something different:

Flatten[Last@Reap[Sow[{##}, #1] & @@@ words, wordsselect, #2 &], 2]
$\endgroup$
3
$\begingroup$
words =
  {{{"w1", "w2"}, 19}, {{"w1", "w3"}, 8}, {{"w1", "w4"}, 7}, 
  {{"w2", "w5"}, 7}, {{"w2", "w5"}, 7}, {{"w3", "w6"}, 7},
  {{"w3", "w7"}, 7}, {{"w3", "w8"}, 6}, {{"w4", "w6"}, 6}};

keys = {"w2", "w4", "w8"};

Using ContainsAny (new in 10.2)

Select[words, ContainsAny[#[[1]], keys] &]

{{{"w1", "w2"}, 19}, {{"w1", "w4"}, 7}, {{"w2", "w5"}, 7}, {{"w2", "w5"}, 7}, {{"w3", "w8"}, 6}, {{"w4", "w6"}, 6}}

Two other possibilities:

Pick[words, ContainsAny[keys] /@ First /@ words];

Cases[words, {{a_, b_}, _} /; MemberQ[keys, a | b]];
$\endgroup$
2
$\begingroup$

Pre v10 without IntersectingQ you can do this:

 Select[words, Length@Intersection[#[[1]], wordsselect] > 0 &]
$\endgroup$
1
$\begingroup$

Using ReplaceAll and MemberQ:

words = {{{"word1", "word2"}, 19}, {{"word1", "word3"}, 8}, 
         {{"word1", "word4"}, 7}, {{"word2", "word5"}, 7}, 
         {{"word2", "word5"}, 7}, {{"word3", "word6"}, 7}, 
         {{"word3", "word7"}, 7}, {{"word3", "word8"}, 6},
         {{"word4", "word6"}, 6}};

keys = {"word2", "word4", "word8"};

wordsnew = {{{"word1", "word2"}, 19}, {{"word1", "word4"}, 7}, 
            {{"word2", "word5"}, 7}, {{"word2", "word5"}, 7}, 
            {{"word3", "word8"}, 6}, {{"word4", "word6"}, 6}};

words /. {x : {__}, y_} /; ! MemberQ[keys, Alternatives @@ x] :> Nothing

% === wordsnew

(*True*)

Or using ReplaceAll and IntersectingQ:

words /. {x : {__}, y_} /; ! IntersectingQ[keys, x] :> Nothing

% === wordsnew

(*True*)
$\endgroup$
1
$\begingroup$

Some variations:

words = {{{"w1", "w2"}, 19}, {{"w1", "w3"}, 8}, {{"w1", "w4"}, 
    7}, {{"w2", "w5"}, 7}, {{"w2", "w5"}, 7}, {{"w3", "w6"}, 
    7}, {{"w3", "w7"}, 7}, {{"w3", "w8"}, 6}, {{"w4", "w6"}, 6}};

keys = {"w2", "w4", "w8"};

Select[words, ! DisjointQ[keys, First@#] &]

Pick[words, AnyTrue[MemberQ[#, Alternatives @@ keys] &] /@ words]

Select[AnyTrue[MemberQ[#, Alternatives @@ keys] &]][words]

Pick[words, IntersectingQ[keys, First@# ] & /@ words]

{{{"w1", "w2"}, 19}, {{"w1", "w4"}, 7}, {{"w2", "w5"}, 7}, {{"w2", "w5"}, 7}, {{"w3", "w8"}, 6}, {{"w4", "w6"}, 6}}

$\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.