1
$\begingroup$

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.

$\endgroup$
4
  • $\begingroup$ StringPosition can take a third integer argument to return the first n 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$
    – flinty
    Commented Sep 11, 2020 at 18:07
  • 1
    $\begingroup$ Also, what do you mean by "context of the word" ? To get the nth match, you could just do pos = StringPosition[sentence,"car"] then pos[[n]] surely? $\endgroup$
    – flinty
    Commented Sep 11, 2020 at 18:21
  • $\begingroup$ So I want to find the position of all specific instances of the word "car", not get rid of duplicates. The above result does not give the position of the second instance of the word "car". You could manually get the nth match in the above fashion, but that defeats the purpose of having a function do it. $\endgroup$
    – Mualpha7
    Commented Sep 14, 2020 at 2:34
  • $\begingroup$ I think I figured a way to do it. The Sort function comes in handy to do DeleteDuplicates[ 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$
    – Mualpha7
    Commented Sep 14, 2020 at 13:09

2 Answers 2

0
$\begingroup$
StringPosition[str, WordCharacter .., Overlaps -> False]
 {{1, 3}, {5, 10}, {12, 14}, {16, 18}, {20, 21}, {23, 25}, {27, 29}, {31, 40}}
$\endgroup$
0
$\begingroup$

DeleteDuplicates[Sort[Flatten[StringPosition["Bob bought his car at the car dealership", #] & /@ TextWords@"Bob bought his car at the car dealership", 1]]] gives us {{1, 3}, {5, 10}, {12, 14}, {16, 18}, {20, 21}, {23, 25}, {27, 29}, {31, 40}}

$\endgroup$

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