5

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?

Al Guy
  • 1,610
  • 1
  • 10
  • 15

4 Answers4

10

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

Bob Hanlon
  • 157,611
  • 7
  • 77
  • 198
5

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).

ciao
  • 25,774
  • 2
  • 58
  • 139
5

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|>
m_goldberg
  • 107,779
  • 16
  • 103
  • 257
  • Actually already in Mathematica 5 Select accepts third argument limiting the number of matches it returns, so your third statement is incorrect. – Alexey Popkov Jun 14 '16 at 00:10
4

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}

Alexey Popkov
  • 61,809
  • 7
  • 149
  • 368