1
$\begingroup$

Take the list

e = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

I want to get the nearest points but with a wraparound condition. So lets say I want to find the 5 nearest points to 2, typically writing Nearest[e,2,4] would result in

{1,2,3,4,5} 

I want it to wrap around to the end of the list, such that I get

{10,1,2,3,4}

I would also like to use it with the format of Nearest[e,2,{Infinity,5}]. I've read up on the Nearest in the documentation, and I think I have to define a NearestFunction however I'm still not sure how I would go about doing this. Of course I'd like it to wrap both sides of the list.

$\endgroup$
0

2 Answers 2

1
$\begingroup$

I think the following NearestFunction does what you want:

nf = Nearest[
    Range[10],
    DistanceFunction -> (Min[Mod[{-1,1} (#1-#2), 10]]&)
];

A couple examples:

nf[2, 5]
nf[1, {Infinity, 2.1}]

{2, 1, 3, 4, 10}

{1, 2, 10, 3, 9}

Note that the order is from closest to farthest, with ties going to the entries that appear first in the dataset.

$\endgroup$
3
  • $\begingroup$ This is the setup I was going for, it doesn't however work on the kind of list I am looking at. Take for example the following list: e={0., 14.0362, 18.4349, 26.5651, 33.6901, 36.8699, 45., 53.1301, 56.3099, 63.4349, 71.5651, 75.9638, 90., 104.036, 108.435, 116.565, 123.69, 126.87, 135., 143.13, 146.31, 153.435, 161.565, 165.964, 180.} Using the above as nf = Nearest[ e, DistanceFunction -> (Min[Mod[{-1,1} (#1-#2),Length@e]]&) ]; With nf[45, 5] does not quite give what one would expect $\endgroup$ Commented Jun 6, 2017 at 19:05
  • $\begingroup$ Why are you using Length[e] instead of 180? $\endgroup$
    – Carl Woll
    Commented Jun 6, 2017 at 19:07
  • $\begingroup$ Oh yes, of course!! That was silly of me. Well then this works just great :) I am going to change this to the answer as it answers my question in the desired manner. However, both your and @george2079 solutions work. $\endgroup$ Commented Jun 6, 2017 at 19:08
1
$\begingroup$

maybe there are more elegant approaches but this is i think what you are after:

e = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
target = Position[e, 2][[1, 1]]
Flatten[ConstantArray[e, 3]]
    [[target + Length@e - 2 ;;  target + Length@e + 2]]

{10, 1, 2, 3, 4}

or maybe this:

cyclicpart[list_, n_] := list[[Mod[ n - 1, Length@e] + 1]]
Table[cyclicpart[e, i], {i, target - 2, target + 2}]

{10, 1, 2, 3, 4}

Edit: using Nearest

angles = RandomReal[{0, 180}, {20}];
(*just to show they need not be ordered*)
nf = Nearest[angles, 
  DistanceFunction :> (Min[Abs[Mod[#2 - #1, 180] - {0, 180}]] & )];
   nf[2, 7]

{177.429, 11.5476, 17.0088, 164.773, 159.163, 27.8531, 144.853}

demo:

Manipulate[Show[
  Graphics@{ {Blue, Line[{{p, -2}, {p, 4}}]}, 
    Point[{#, 0}] & /@ angles,
    {Red, Point[{#, 2}] & /@ nf[p, 7]}}], {{p, 0}, 0, 180}]
$\endgroup$
2
  • $\begingroup$ Interesting, with a bit of editing I can get it to work for my purposes. The idea is the list is ordered. It is a list of angles, ranging from 0 to 180, with periodicity given by Mod[a, 180]. I need to find all angles in that list that match a given angle with a specified tolerance. Nearest seemed like the best function for that job, and by giving it some kind or periodicity would allow me to get the job done. I am happy with your version however, it still allows me to do what I needed, Thanks $\endgroup$ Commented Jun 6, 2017 at 18:43
  • $\begingroup$ oh i get it, see edit using Nearest (Though it looks like Carl beat me to it.. ) $\endgroup$
    – george2079
    Commented Jun 6, 2017 at 19:27

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.