          self._patterns.pop(key)
          self._raw_patterns.pop(key)
          self._tree.pop(key)
          self._root.pop(key)
          self._tokens_to_key.pop(key)
  
      def _get_keys_to_position_maps(self, doc):
          """
          Processes the doc and groups all matches by their root and match id.
          Returns a dict mapping each (root, match id) pair to the list of
 
</s> remove         for i, current_patterns in enumerate(_patterns):
 </s> add         for i, current_patterns in enumerate(_patterns, start=pattern_offset):
        for mklist in self._tokens_to_key.pop(key):
            for mkey in mklist:
                self._matcher.remove(mkey)
          self._patterns.pop(key)
          self._raw_patterns.pop(key)
          self._tree.pop(key)
          self._root.pop(key)
        for mklist in self._tokens_to_key.pop(key):
            for mkey in mklist:
                self._matcher.remove(mkey)
  
      def _get_keys_to_position_maps(self, doc):
          """
          Processes the doc and groups all matches by their root and match id.
          Returns a dict mapping each (root, match id) pair to the list of
keep keep keep keep replace keep keep keep keep keep
 Fix Dependency Matcher Ordering Issue (#9337)

* Fix inconsistency

This makes the failing test pass, so that behavior is consistent whether
patterns are added in one call or two.

The issue is that the hash for patterns depended on the index of the
pattern in the list of current patterns, not the list of total patterns,
so a second call would get identical match ids.

* Add illustrative test case

* Add failing test for remove case

Patterns are not removed from the internal matcher on calls to remove,
which causes spurious weird matches (or misses).

* Fix removal issue

Remove patterns from the internal matcher.

* Check that the single add call also gets no matches 
spacy/matcher/dependencymatcher.pyx