11
$\begingroup$

I have a list of pairs of values. Some of those pairs are invalid based on another list. I would like to select only the valid pairs.

list1 = {"abc", "def", "ghi", "jkl", "mno"};
list2 = {{"abc", 1}, {"def", 2}, {"ghi", 3}, {"jkl", 4}, {"mno", 5}};
sel = {{2}, {}, {4}, {1}, {7}};
Pick[list1, sel, {_}]
Pick[list2, sel, {_}]

list1 is a sample of what I would like. list2 is similar to my actual case. sel is the result of Position where I'm checking a corresponding list against valid cases. When the result of Position is an empty list, I do not want the values in list1 or list2.

The output from the above code is:

enter image description here

I see from the documentation that what I'm doing with list2 is not valid. My question is what is a good way to do this? I want my original list2, but without {"def",2}. Everything I can think of is pretty messy.

$\endgroup$

3 Answers 3

13
$\begingroup$

One way will be to pre-process sel before using it with Pick e.g.:

sel = sel /. {} -> {-1} // Flatten // Sign;

Here I'm assuming the integers in sel will always be positive since you say it's from a Position call.

Pick[list2, sel, 1]
{{"abc", 1}, {"ghi", 3}, {"jkl", 4}, {"mno", 5}}
$\endgroup$
1
  • $\begingroup$ That works perfectly. I had assumed (incorrectly) that the problem with using list2 was that sel didn't have pairs of values. I didn't realize the empty list was causing the problem. Why didn't that cause a problem with list1? $\endgroup$ Commented Sep 5, 2014 at 20:14
6
$\begingroup$
list2[[Flatten[Position[sel, {_}]]]]

(*{{"abc", 1}, {"ghi", 3}, {"jkl", 4}, {"mno", 5}}*)

or simply:

list2 ~Extract~ Position[sel, {_}]     (* thanks to  Mr.Wizard*)

 (*{{"abc", 1}, {"ghi", 3}, {"jkl", 4}, {"mno", 5}}*)
$\endgroup$
2
  • 2
    $\begingroup$ I forgot that the question wasn't really how to make Pick work but how to perform this operation. +1 FWIW this is a little cleaner: list2 ~Extract~ Position[sel, {_}] $\endgroup$
    – Mr.Wizard
    Commented Sep 6, 2014 at 11:21
  • $\begingroup$ Great. thanks a lot. $\endgroup$ Commented Sep 6, 2014 at 21:16
4
$\begingroup$

I covered this to some degree in my answer to: Plot columns of table if some condition is fulfilled.

You should be aware that the behavior of Pick that causes your error is also one of its most powerful attributes. It can handle arbitrary expression structure:

Pick[
 foo[a, bar[b, baz[c, d], e]],
 foo[r, bar[q, baz[q, r], r]],
 q
]
foo[bar[b, baz[c]]]

The heads of the selection expression may be List even if the the heads of the primary expression are not:

Pick[
 foo[a, bar[b, baz[c, d], e]],
 {r, {q, {q, r}, r}},
 q
]
foo[bar[b, baz[c]]]

I illustrate this only in case you (or other readers) think that the behavior of Pick is a bug.

The solution shown in my linked answer is essentially the same as RunnyKine's above, except that I prefer to resolve the selection expression to True and False directly. For your example:

Pick[list2, MatchQ[{_}] /@ sel]
{{"abc", 1}, {"ghi", 3}, {"jkl", 4}, {"mno", 5}}

Or if you do not have the version 10 operator form of MatchQ:

Pick[list2, MatchQ[#, {_}] & /@ sel]
$\endgroup$
1
  • $\begingroup$ Thanks - that also helps me better tie together the operator form and the "traditional" form. Also Pick does not work as I had expected it to, thanks for explaining. $\endgroup$ Commented Sep 6, 2014 at 20:24

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.