5
$\begingroup$

What is the difference between having Cases with selection condition presented by pattern and a with pure function as condition? What are the internal implementational reasons to have them separate?

As a side question: How can I select from a list of integers those that have a difference with their neighbor ( left or right, or both) unity?

$\endgroup$
2
  • $\begingroup$ Can you give us an example of your first case? It's related to the second? $\endgroup$
    – Murta
    Commented Aug 9, 2015 at 3:14
  • $\begingroup$ Regarding the side question also see: (23607) $\endgroup$
    – Mr.Wizard
    Commented Aug 9, 2015 at 7:18

4 Answers 4

10
$\begingroup$

Any criteria (used for Select) can be written as the pattern _?(criteria) (used for Cases or DeleteCases). For single argument functions, the pure function can be abbreviated

list = Range[20];

Select[list, EvenQ[#] &] ==
 Select[list, EvenQ] ==
 Cases[list, _?(EvenQ[#] &)] ==
 Cases[list, _?EvenQ] ==
 DeleteCases[list, _?(! EvenQ[#] &)] ==
 DeleteCases[list, _?(OddQ[#] &)] ==
 DeleteCases[list, _?OddQ] ==
 Pick[list, EvenQ[list]] ==
 Range[2, 20, 2]

True

$\endgroup$
5
$\begingroup$

For the second part of question:

(n.b.: If you want positions instead of elements, change #[[Union[p - 1, p]]] to Union[p - 1, p].)

With[{p = Pick[Range@Length@#, Abs[Differences@Prepend[#, #[[1]] - 2]], 1]},
              #[[Union[p - 1, p]]]] &@theList

This will be much faster on larger lists then the solution based on Split from Alexey Popkov (which I up-voted - it's canonical and clean).

$\endgroup$
5
$\begingroup$

This is aimed at the first part of your question. I do not claim it is exhaustive.

Cases and Select behave differently in many situations.

Things Cases can do that Select can't

  • take a level specification
  • match and replace.
  • take an argument limiting the number of matches it returns

Cases and Select treat associations differently.

assoc = <|a -> 1, b -> 2|>;
assoc // Cases[_?(# > 1 &)]
{2}
assoc // Select[# > 1 &]
<|b -> 2|>
$\endgroup$
1
  • $\begingroup$ Actually already in Mathematica 5 Select accepts third argument limiting the number of matches it returns, so your third statement is incorrect. $\endgroup$ Commented Jun 14, 2016 at 0:10
4
$\begingroup$

For your second question

How can I select from a list of integers those that have a difference with their neighbor ( left or right, or both) unity?

you could use:

lst = RandomInteger[10, 10]
Flatten@Select[Split[lst, Abs[#1 - #2] == 1 &], Length[#] > 1 &]
{8, 7, 5, 7, 0, 7, 6, 1, 1, 2}

{8, 7, 7, 6, 1, 2}
$\endgroup$

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