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 at 23:11
  • $\begingroup$ error because the left hand would fall out of the boundary of the list $\endgroup$ – Ali Mohammadi Apr 11 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.

| improve this answer | |
$\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
| improve this answer | |
$\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]]}
| improve this answer | |
$\endgroup$
  • $\begingroup$ This only returns the right side of the window. $\endgroup$ – Rohit Namjoshi Apr 12 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 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 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." *)
| improve this answer | |
$\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 at 23:39
  • $\begingroup$ the list should be flat so meeting this condition isn't crucial $\endgroup$ – Ali Mohammadi Apr 11 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 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.