# Test for list member positions

Let's say there is a list like: l1={1,2,3,4,5,6,7,8} If you're given some arbitrary element and a distance, how do you find the of list elements that are that distance away from the element. For example get: {1,7}when the following is called: [l1,4,3] I can't quit make the connection between position and the built it Nearest[] function. Would Nearest[] even be useful in this case or should I look at actual list operations?

• What result do you expect for [l1, 4, 4]? – Rohit Namjoshi Apr 11 at 23:11
• error because the left hand would fall out of the boundary of the list – Ali Mohammadi Apr 11 at 23:14

A quick thing. I'd just use normal list operations and keep it simple.

get[list_List, ele_, (dist_Integer)?Positive] :=
Module[{p, res = {}, n},
p = Flatten@Position[list, ele];
Do[
If[p[[n]] - dist >= 1,
AppendTo[res, list[[p[[n]] - dist]]]
];
If[p[[n]] + dist <= Length@list,
AppendTo[res, list[[p[[n]] + dist]]]
]
,
{n, 1, Length@p}
];
res
]


Then

  get[{1, 2, 3, 4, 5, 6, 7, 8}, 4, 3] get[{1, 2, 3, 4, 5, 6, 7, 8}, 4, 4] get[{1, 2, 3, 4, 5, 6, 7, 8, 4}, 4, 3] get[{1, 2, 3, 4, 5, 6, 7, 8, 4}, 4, 7] get[{1, 2, 3, 4, 5, -5, 7, 8, 4}, -5, 3] Bug reports are welcome and will be processed in the order they are received.

ClearAll[g]
g[l_List, e_, d_Integer?Positive] := l[[Select[1 <= # <= Length[l] &]@
Flatten @ Function[x, {d, -d} + x, Listable] @ Position[l, e]]]


Using Nasser's example inputs:

inputs = {{{1, 2, 3, 4, 5, 6, 7, 8}, 4, 3},
{{1, 2, 3, 4, 5, 6, 7, 8},  4, 4},
{{1, 2, 3, 4, 5, 6, 7, 8}, 4, 5},
{{1, 2, 3, 4, 5, 6, 7, 8, 4}, 4, 3},
{{1, 2, 3, 4, 5, 6, 7, 8, 4}, 4, 7},
{{1, 2, 3, 4, 5, -5, 7, 8, 4}, -5, 3}};

g @@@ inputs

  {{1, 7}, {8}, {}, {1, 7, 6}, {2}, {3, 4}}

Grid[Prepend[{##, g@##} & @@@ inputs, {"lst", "e", "d", "g[lst, e, d]"}], Dividers -> All] Alternatively, you can use SequenceCases:

ClearAll[g2]
g2[l_List, e_, d_Integer?Positive] := SequenceCases[l,
{a_, Repeated[_, {d - 1}], e} | {e, Repeated[_, {d - 1}], b_} :> Sequence[a, b],
Overlaps -> True];

g2 @@@ inputs == g @@@ inputs

True

f[l_List, r_Integer, q_Integer] := l[[Position[l, r][[1, 1]] + q]]

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

f[ll,5,3]


(* 6 *)

or obviously if you need both sides:

f[l_List, r_Integer, q_Integer] := {l[[Position[l, r][[1, 1]] + q]],
l[[Position[l, r][[1, 1]] - q]]}

• This only returns the right side of the window. – Rohit Namjoshi Apr 12 at 13:39
• Using the 'both sides' solution above: f[{1, 2}, 1, 1] evaluates to {2, List} which is wrong. – Rohit Namjoshi Apr 13 at 20:41
• The OP answered your question above ("What result do you expect for [l1, 4, 4]"): error because the left hand would fall out of the boundary of the list. Read "Error" for "List" – David G. Stork Apr 13 at 21:07

Here is another way using list operations. Modify the error handling to suit your needs.

ClearAll@f;

f[list_List, value_, (distance_Integer)?Positive] :=
Module[{pos = FirstPosition[list, value][]},
If[pos - distance < 1 || pos + distance > Length@list, Throw["Out of bounds"]];
Extract[list, {{pos - distance}, {pos + distance}}] // Flatten]

l1 = {1, 2, 3, 4, 5, 6, 7, 8};

f[l1, 4, 3]
(* {1, 7} *)

f[l1, 4, 1]
(* {3, 5} *)

f[l1, 4, 4]
(* "Uncaught Throw["Out of bounds"] returned to top level." *)

• hi. This does not work for all cases. Try f[{1, 2, 3, 4, 5, 6, 7, 8, 4}, 4, 3] it returns {1,7} but it should be {1,7,6} because there can be more than one element that match in the list. You only used the first one found. – Nasser Apr 11 at 23:39
• the list should be flat so meeting this condition isn't crucial – Ali Mohammadi Apr 11 at 23:58
• @Nasser Actually according to @Ali that should return an error since there is no element to the right of the last 4. Anyway, it is really simple to change my answer to use Position rather than FirstPosition to deal with duplicates. – Rohit Namjoshi Apr 12 at 2:02