title: Spacy 3.0 Matcher remove overlaps and preserve the information for the pattern used
body: <p>Is there a shorter, cleaner or built-in method to remove the overlap matched results from the Matcher but also preserve the value of the Pattern that was used for the matching? So that you can tell which pattern gives the match results. The pattern ID is originally given from the matcher results, but the solutions that get rid of the overlap that I have seen drop the ID numbers.</p>
  <p>Here is what I am currently using as the solution, which works but is a bit long:</p>
  <pre><code>import spacy
  from spacy.lang.en import English
  from spacy.matcher import Matcher
  
  text =&quot;United States vs Canada, Canada vs United States, United States vs United Kingdom, Mark Jefferson vs College, Clown vs Jack Cadwell Jr., South America Snakes vs Lopp, United States of America, People vs Jack Spicer&quot;
  
  doc = nlp(text)
  
  #Matcher
  matcher=Matcher(nlp.vocab) 
  # Two patterns
  pattern1 = [{&quot;POS&quot;: &quot;PROPN&quot;, &quot;OP&quot;: &quot;+&quot;, &quot;IS_TITLE&quot;:True}, {&quot;TEXT&quot;: {&quot;REGEX&quot;: &quot;vs$&quot;}}, {&quot;POS&quot;: &quot;PROPN&quot;, &quot;OP&quot;: &quot;+&quot;, &quot;IS_TITLE&quot;:True}]
  pattern2 =[{&quot;POS&quot;: &quot;ADP&quot;},{&quot;POS&quot;: &quot;PROPN&quot;, &quot;IS_TITLE&quot;:True}]
  matcher.add(&quot;Games&quot;, [pattern1])
  matcher.add(&quot;States&quot;, [pattern2])
  
  #Output stored as list of tuples with the following: (pattern name ID, pattern start, pattern end) 
  matches = matcher(doc)
  </code></pre>
  <p>First I stored results in dictionary with a list of tuples as the values and the pattern name as the key</p>
  <pre><code>result = {}
  for key, subkey, value in matches:
      result.setdefault(nlp.vocab.strings[key], []).append((subkey,value))
  print(result)
  </code></pre>
  <p>Which prints out to:</p>
  <pre><code>{'States': [(2, 4), (6, 8), (12, 14), (18, 20), (22, 24), (30, 32), (35, 37), (39, 41)],
  
   'Games': [(1, 4), (0, 4), (5, 8), (5, 9), (11, 14), (10, 14), (11, 15), (10, 15), (17, 20),
    (16, 20), (21, 24), (21, 25), (21, 26), (38, 41), (38, 42)]}
  </code></pre>
  <p>Then I iterated over the results and used <code>filter_spans</code> to remove the overlap and append the start and ends as tuples:</p>
  <pre><code>for key, value in result.items():
      new_vals = [doc[start:end] for start, end in value]
      val2 =[]
      for span in spacy.util.filter_spans(new_vals):
          val2.append((span.start, span.end))
      result[key]=val2
  
  print(result)
  </code></pre>
  <p>This prints a list of results with no overlap:</p>
  <pre><code>{'States': [(2, 4), (6, 8), (12, 14), (18, 20), (22, 24), (30, 32), (35, 37), (39, 41)], 
  
  'Games': [(0, 4), (5, 9), (10, 15), (16, 20), (21, 26), (38, 42)]}
  </code></pre>
  <p>To get the text values just loop the pattern and print the span:</p>
  <pre><code>print (&quot;---Games---&quot;)
  for start, end in result['Games']:
      span =doc[start:end] 
      print (span.text)
  
  print (&quot; &quot;)
  
  print (&quot;---States---&quot;)
  for start, end in result['States']:
      span =doc[start:end] 
      print (span.text)
  </code></pre>
  <p>The output:</p>
  <pre><code>---Games---
  United States vs Canada
  Canada vs United States
  United States vs United Kingdom
  Mark Jefferson vs College
  Clown vs Jack Cadwell Jr.
  People vs Jack Spicer
   
  ---States---
  vs Canada
  vs United
  vs United
  vs College
  vs Jack
  vs Lopp
  of America
  vs Jack
  </code></pre>