2
$\begingroup$

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?

$\endgroup$
2
  • $\begingroup$ What result do you expect for [l1, 4, 4]? $\endgroup$ Apr 11, 2020 at 23:11
  • $\begingroup$ error because the left hand would fall out of the boundary of the list $\endgroup$ Apr 11, 2020 at 23:14

4 Answers 4

3
$\begingroup$

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]

Mathematica graphics

  get[{1, 2, 3, 4, 5, 6, 7, 8}, 4, 4]

Mathematica graphics

  get[{1, 2, 3, 4, 5, 6, 7, 8, 4}, 4, 3]

Mathematica graphics

  get[{1, 2, 3, 4, 5, 6, 7, 8, 4}, 4, 7]

Mathematica graphics

  get[{1, 2, 3, 4, 5, -5, 7, 8, 4}, -5, 3]

Mathematica graphics

Bug reports are welcome and will be processed in the order they are received.

$\endgroup$
2
$\begingroup$
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]

enter image description here

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
$\endgroup$
2
$\begingroup$
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]]}
$\endgroup$
3
  • $\begingroup$ This only returns the right side of the window. $\endgroup$ Apr 12, 2020 at 13:39
  • $\begingroup$ Using the 'both sides' solution above: f[{1, 2}, 1, 1] evaluates to {2, List} which is wrong. $\endgroup$ Apr 13, 2020 at 20:41
  • $\begingroup$ 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" $\endgroup$ Apr 13, 2020 at 21:07
0
$\begingroup$

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][[1]]},
  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." *)
$\endgroup$
3
  • 1
    $\begingroup$ 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. $\endgroup$
    – Nasser
    Apr 11, 2020 at 23:39
  • $\begingroup$ the list should be flat so meeting this condition isn't crucial $\endgroup$ Apr 11, 2020 at 23:58
  • $\begingroup$ @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. $\endgroup$ Apr 12, 2020 at 2:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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