# How to find the nearest string to another string in a mixed array

I am trying to find which string is nearest to another string in an array of numbers and strings. For example, say I have an array that is as follows

testarray={0,0,0,"apple",0,0,0,"pear",0,0,0,0,0,"pineapple"}


I want a general way to find that "apple" is nearest to "pear". Is there an efficient way to do this?

Thanks!

If you want to specify a string in advance and find the position of another string closest to the original, you could do something like this:

positionOfApple = Position[testarray, "apple"]
(* {{4}} *)

closestToApple =
Nearest[Complement[Position[testarray, _String], positionOfApple], positionOfApple]
(* {{{8}}} *)

Extract[testarray, #] & /@ closestToApple
(* {{"pear"}} *)


If instead you are wanting to find a pair of strings with minimal distance between them...

closest =
MinimalBy[Partition[Position[testarray, _String], 2, 1], Abs@*Apply[Subtract]@*Flatten]
(* {{{4}, {8}}} *)

Extract[testarray, #] & /@ closest
(* {{"apple", "pear"}} *)

• I'm interpreting "nearest" to be referring to position within testarray. If you mean "nearest" with regard to something like Levenshtein distance, then the answer will depend on EditDistance, or something similar. May 10, 2022 at 22:16

Just for fun, another option is to write your own distance function

t = {0, 0, 0, "apple", 0, 0, 0, "pear", 0, 0, 0, 0, 0, "pineapple"}
nearItem = "pear";
f[x_, y_] := Module[{dist = 10^6},
If[StringQ[y] && y != nearItem,
dist = Abs[Position[t, x][[1, 1]] - Position[t, y][[1, 1]]]
];
dist
]

Nearest[t, nearItem, DistanceFunction -> f]

{"apple"}


When

t = {"apple", 0, 0, 0, 0, 0, 0, "pear", 0, 0, 0, 0, 0, "pineapple"}


It gives

{"pineapple"}


And when there are two equal distance ones, it gives

t = {0, "apple", 0, 0, 0, 0, 0, "pear", 0, 0, 0, 0, 0, "pineapple"}
{"apple", "pineapple"}


You can modify your distance function as needed.

testarray = {0, 0, 0, "apple", 0, 0, 0, "pear", 0, 0, 0, 0, 0, "pineapple"}


Extract positions of strings:

pos = Position[testarray, _String]


{{4}, {8}, {14}}

strs = Extract[testarray, pos]


{"apple", "pear", "pineapple"}

Make subsets of pairs:

ssets = Subsets[strs, {2}]


{{"apple", "pear"}, {"apple", "pineapple"}, {"pear", "pineapple"}}

Define a distance function:

dist[{a_, b_}] :=
Det@Position[testarray, b] - Det@Position[testarray, a]

Transpose[{Rule @@@ ssets, dist /@ ssets}] // TableForm


$$\left( \begin{array}{cc} \text{apple}\to \text{pear} & 4 \\ \text{apple}\to \text{pineapple} & 10 \\ \text{pear}\to \text{pineapple} & 6 \\ \end{array} \right)$$

This can be sorted based on distance or as required.