How can I write a rule in spacy with pattern inside a pattern (nested pattern)

Viewed 72

I would like to write a pattern in Spacy that matches a text and then optionally all the parenthesis at the right of the text if there is any.

For example, for the following texts, I give as input the left part of the arrow "->" and expect as an output the right part of the arrow.

However, we found that This Example (TE (as explained above) other stuff) -> This Example (TE (as explained above) other stuff)

Here is another example This Example (TE (some text here)) -> This Example (TE (some text here))

Some random text and then This Example (TE) -> This Example (TE)

Then a final example This Example -> This Example

These texts are not fixed and work as an example.

I would like to get as many starting parenthesis as ending (possibly even no parenthesis pattern)

I tried the following but it does not work.

patt_1 = [
    {"OP": "+", "LOWER": {"IN": ['this','example']}},
    {"OP": "*", "LOWER": {"IN":["("]}},
    {"OP": "*", "POS": {"IN":["ADJ", "PROPN", "NOUN", "CCONJ", "NUM", "ADV"]}},
    {"OP": "*", "LOWER": {"IN": [")"]}}
]

It matches only the first parenthesis. Since I operate on long texts I would also like to match a short phrase and not the entire document if there is a right parenthesis at the end.

I would like something like the following but it does not work ...


patt_1 = [
{"OP": "+", "LOWER": {"IN":["("]}},
{"OP": "+", "POS": {"IN":["ADJ", "PROPN", "NOUN"]}},
{"OP": "+", "LOWER": {"IN": [")"]}}
]
patt_2 = [
{"OP": "+", "LOWER": {"IN":["("]}},
{"OP": "+", "POS": {"IN":["ADJ", "PROPN", "NOUN"]}},
{"OP": "+", "LOWER": {"IN":["("]}},
{"OP": "+", "POS": {"IN":["ADJ", "PROPN", "NOUN"]}},
{"OP": "+", "LOWER": {"IN": [")"]}},
{"OP": "+", "POS": {"IN":["ADJ", "PROPN", "NOUN"]}},
{"OP": "+", "LOWER": {"IN": [")"]}}
]

patt_3 = [
    {"OP": "+", "LOWER": {"IN": ['this','example']}},
    { "OP": "*", patt_1},
    { "OP": "*", patt_2}
]

Thank you for your help

1 Answers

If all the texts have the same pattern, you can use regex to identify the correct part.

import re

text = "However, we found that This Example (TE (as explained above) other stuff)"
cleaned_text = re.sub(r"However, we found that ", "", text).strip()
print(cleaned_text) # Outputs "This Example (TE (as explained above) other stuff)"

Edit (see comments):

specific_phrase = "This Example"
example_document = "However, we found that This Example (TE (as explained above) other stuff)"
brackets_regex = r" \(.*\)"

if re.search(specific_phrase, example_document) and re.search(brackets_regex, example_document):
    matched_pattern = specific_phrase + re.search(brackets_regex, example_document).group()
print(matched_pattern) # Output: This Example (TE (as explained above) other stuff)

This can then be put into a function and then loop over your documents to process them.

Related