13
$\begingroup$

Given

t1 = {3, 2, 8, 6, 1, 9, 4, 1, 5, 0}

I want to get all the elements which are greater than the right neighbor. The result would be

{3, 8, 6, 9, 4, 5}

I can do it by

t2 = Partition[t1, 2, 1]
Select[t2, #[[1]] > #[[2]] &][[All, 1]]

But I am looking for a solution like

Select[t1, #1 > #2 &]

which does not work

$\endgroup$
1
  • 4
    $\begingroup$ Most[Last /@ Split[t1, Less]]? $\endgroup$ Commented Aug 16, 2023 at 17:43

14 Answers 14

13
$\begingroup$

1.

Pick[Most @ t1, UnitStep @ Differences @ t1, 0]
{3, 8, 6, 9, 4, 5}

2.

t1[[Random`Private`PositionsOf[UnitStep @ Differences @ t1, 0]]]
{3, 8, 6, 9, 4, 5}
$\endgroup$
1
  • 1
    $\begingroup$ Pick[Most @ t1, Sign @ Differences @ t1, -1] $\endgroup$ Commented Aug 23, 2023 at 13:35
13
$\begingroup$

We MapApply Greater on partitions of the list with offset, then use Pick to select all the valid elements.

list = {3, 2, 8, 6, 1, 9, 4, 1, 5, 0};

Pick[Most@list, Greater @@@ Partition[list, 2, 1], True]

(* Out: {3, 8, 6, 9, 4, 5} *)

Performance

Here is the performance of this answer compare to others on a list of 1,000 random integers in Mathematica 13.3:

Answer RepeatedTiming MaxMemoryUsed
kglr's Pick - 1 0.000014 30880
kglr's Pick - 2 0.000015 22632
Ben's Pick 0.00041 184984
Syed Split 0.00044 93920
ydd's Ordering 0.00082 124112
Daniel Huber's MapIndexed 0.002 281848
lericr's SequenceCases 1.9 4522768
$\endgroup$
11
$\begingroup$

Maybe this?

SequenceCases[t1, {a_, _}?(Apply[Greater]) :> a, Overlaps -> True]
$\endgroup$
1
  • 2
    $\begingroup$ A bit neater perhaps: SequenceCases[list, ({a_, b_} /; (a > b)) :> a, Overlaps -> True] $\endgroup$
    – SHuisman
    Commented Aug 16, 2023 at 19:07
11
$\begingroup$

You can do this using "MapIndexed". This delivers not only the list element, but as second argument also its position. Increasing this by one, you can reach the next element. Look it up in the help.

t1 = {3, 2, 8, 6, 1, 9, 4, 1, 5, 0};
MapIndexed[If[#1 > t1[[#2[[1]] + 1]], #1, Nothing[]] &, Most@t1]
$\endgroup$
11
$\begingroup$
t1 = {3, 2, 8, 6, 1, 9, 4, 1, 5, 0};

Using FoldPairList:

FoldPairList[If[#1 > #2, {#1, #2}, {, #2}] &, t1] /. Null -> Nothing

Using Split:

Split[t1, #1 > #2 &] // Map[Most] // Flatten

or alternatively:

Split[t1, Greater] // Map[Most] // Flatten

Original answer (didn't read the post all the way; it was already there)

First /@ Select[Partition[t1, 2, 1], First@# > Last@# &]

or using the operator form:

Map[First][Select[First@# > Last@# &][Partition[t1, 2, 1]]]

Result

{3, 8, 6, 9, 4, 5}

$\endgroup$
9
$\begingroup$

Perhaps the DeleteAdjacentDuplicates can be abused:

list={3,2,8,6,1,9,4,1,5,0};
Most[Reverse@DeleteAdjacentDuplicates[Reverse@list, Greater]]
$\endgroup$
8
$\begingroup$

Could take the differences in the ordering of the ordering and select where it's less than 0

t1[[Position[Differences@Ordering@Ordering[t1], n_ /; n < 0] // 
   Flatten]]

Basically the same thing but using RotateLeft:

t1[[Position[Most[t1 - RotateLeft[t1]], n_ /; n > 0]//Flatten]]
$\endgroup$
5
$\begingroup$

Using Sow and Reap.

fun[u_] := 
 Reap[Sow @@@ 
    Thread[{u, 
      ArrayPad[Sign@*Differences@u, {0, 1}, "x"]}], -1, #2 &][[2, 1]]

Testing:

t1 = {3, 2, 8, 6, 1, 9, 4, 1, 5, 0}
fun[t1]

yields: {3, 8, 6, 9, 4, 5}

# -> fun[#] & /@ RandomInteger[10, {10, 10}] // Column

enter image description here

$\endgroup$
5
$\begingroup$

Another way using GroupBy and Lookup:

Lookup[GroupBy[Partition[t1, 2, 1], #[[1]] > #[[2]] &, #[[All, 1]] &], True]

(*{3, 8, 6, 9, 4, 5}*)
$\endgroup$
5
$\begingroup$

Single pass with a loop, no copy:

l = {3, 2, 8, 6, 1, 9, 4, 1, 5, 0} ;
Reap[
   Do[
    With[
     {a = l[[i]], b = l[[i + 1]] },
     If[a > b, Sow[a]]
     ],
    {i, 1, Length[l] - 1}
    ]
   ] // Last // First
$\endgroup$
5
$\begingroup$

Another method:

t1[[Lookup[-1]@PositionIndex@Sign@Differences@t1]]

(* {3, 8, 6, 9, 4, 5} *)

Or, a slight variant with UnitStep instead of Sign:

t1[[Lookup[0]@PositionIndex@UnitStep@Differences@t1]]   
$\endgroup$
4
$\begingroup$
Cases[{a_, b_} /; a > b :> a] @ Partition[list, 2, 1]

{3, 8, 6, 9, 4, 5}

$\endgroup$
4
$\begingroup$
t1 = {3, 2, 8, 6, 1, 9, 4, 1, 5, 0};

k={t1[[#]],(t1[[#]]-t1[[#+1]])}&/@Range[Length[t1]-1];

First/@Select[k,#[[2]]≥0&]

Resultat

{3,8,6,9,4,5}

Autre code:

t1 = {3, 2, 8, 6, 1, 9, 4, 1, 5, 0};

k=t1-Insert[TakeList[t1,{1,All}][[2]],0,-1];

Select[Sign[k]*t1,#>0&]

Resultat

{3,8,6,9,4,5}

This code is more speed and simple:

Select[-Sign[Insert[Differences[t1],-1,-1]]*t1,#>0&]
$\endgroup$
2
$\begingroup$
list = {3, 2, 8, 6, 1, 9, 4, 1, 5, 0};

Using SequenceSplit (new in 11.3)

First /@ Catenate @ SequenceSplit[Partition[list, 2, 1], {{a_, b_}} /; a <= b]

{3, 8, 6, 9, 4, 5}

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