Is there a simple way of finding the position of a specific instance of a substring within a string? For instance, in the sentence "Bob bought his car at the car dealership". Something like StringPosition
would give me the position of both instances of car, namely {{16, 18}, {27, 29}}
, but what if I only wanted the first or the second instance of the word?
If I do a StringPosition
on every word of the sentece, both instances of the word "car" would yield {{16, 18}, {27, 29}}
, as opposed to {16, 18}
for the first instance and {27, 29}
for the second instance, which is not very useful.
This seems to be a recurrent theme for a lot of Mathematica's NLP functions when they are applied to text: The functions act on each word, without considering the context of the word within the text. Mathematica just gives you all possible answers for each word.
StringPosition
can take a third integer argument to return the firstn
occurrences. It's not hard to find the positions for the first occurrences of all words:sentence = "Bob bought his car at the car dealership"; words = DeleteDuplicates@TextWords@sentence; AssociationThread[words -> Flatten[StringPosition[sentence, #, 1] & /@ words, 1]]
and the results:{"Bob" -> {1, 3}, "bought" -> {5, 10}, "his" -> {12, 14}, "car" -> {16, 18}, "at" -> {20, 21}, "the" -> {23, 25}, "dealership" -> {31, 40}}
$\endgroup$pos = StringPosition[sentence,"car"]
thenpos[[n]]
surely? $\endgroup$Sort
function comes in handy to doDeleteDuplicates[ Sort[Flatten[StringPosition[sentence, #] & /@ words, 1]]]
. This gives us the desired result{{1, 3}, {5, 10}, {12, 14}, {16, 18}, {20, 21}, {23, 25}, {27, 29}, {31, 40}}
, where the position of each substring (i.e. word) within the string (i.e. sentence) is given. $\endgroup$