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$
  • $\begingroup$ What result do you expect for [l1, 4, 4]? $\endgroup$ – Rohit Namjoshi Apr 11 '20 at 23:11
  • $\begingroup$ error because the left hand would fall out of the boundary of the list $\endgroup$ – Ali Mohammadi Apr 11 '20 at 23:14
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$
  • $\begingroup$ This only returns the right side of the window. $\endgroup$ – Rohit Namjoshi Apr 12 '20 at 13:39
  • $\begingroup$ Using the 'both sides' solution above: f[{1, 2}, 1, 1] evaluates to {2, List} which is wrong. $\endgroup$ – Rohit Namjoshi Apr 13 '20 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$ – David G. Stork Apr 13 '20 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$
  • 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 '20 at 23:39
  • $\begingroup$ the list should be flat so meeting this condition isn't crucial $\endgroup$ – Ali Mohammadi Apr 11 '20 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$ – Rohit Namjoshi Apr 12 '20 at 2:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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