def process_documents(self, documents: List[Dict], unsuccessful_docs: List[Tuple[int, MarqoUpdateDocumentsItem]],
                          is_index_semi_structured = False) -> Tuple[List[Dict], Dict]:
        """Process documents to remove duplicates and identify documents containing maps.
        
        This method combines duplicate removal and map detection into a single pass through
        the documents for better efficiency.

        Args:
            is_index_semi_structured: Variable denoting if the index that's is currently being processed is of type SemiStructured
            unsuccessful_docs: A list of documents which were processed unsuccessfully
            documents: List of document dictionaries to process
            
        Returns:
            Tuple containing:
            - List of deduplicated documents
            - Set of unique document IDs
            - Dictionary of document IDs that contain dictionary values and their index in the documents list
        """
        docs = []
        doc_ids = set()
        documents_with_maps = {}
        
        # Process documents in reverse to keep latest version of duplicates
        for i in range(len(documents) - 1, -1, -1):
            doc = documents[i]
            
            if not isinstance(doc, dict) or '_id' not in doc:
                docs.append(doc)
                continue
                
            doc_id = doc['_id']
            
            try:
                # Skip if we've already seen this ID
                if doc_id is not None and doc_id in doc_ids:
                    logger.debug(f'Duplicate document ID {doc_id} found, keeping the latest')
                    continue
                
                # Check for dictionary values while processing doc to populate the documents_with_maps set.
                # Only do it in case of semi-structured indexes.
                if is_index_semi_structured:
                    for field_name, field_value in doc.items():
                        if isinstance(field_value, dict):
                            if len(field_value) == 0: # If the dictionary is empty, get back the document so that we can update the doc with an empty dictionary (i.e remove the map from the doc).
                                documents_with_maps[doc_id] = i
                            else:
                                for key, val in field_value.items():
                                    if isinstance(val, (int, float)):
                                        documents_with_maps[doc_id] = i
                                        break
                                    else:
                                        raise MarqoDocumentParsingError(
                                            f'Unsupported field type {type(val)} for field {field_name} in doc {doc_id}. We only support int and float types for map values when updating a document.'
                                        )
                            break
                doc_ids.add(doc_id)
                docs.append(doc)
                
            except TypeError as e:
                logger.debug(f'Could not hash document ID {doc_id}: {e}')
                docs.append(doc)

            except MarqoDocumentParsingError as e:
                unsuccessful_docs.append((i, MarqoUpdateDocumentsItem(id=doc.get(MARQO_DOC_ID, ''),
                                                                      error=e.message,
                                                                      status=int(api_exceptions.InvalidArgError.status_code))))

        # Reverse to preserve original order
        docs.reverse()
        return docs, documents_with_maps
Process documents to remove duplicates and identify documents containing maps.
        
        This method combines duplicate removal and map detection into a single pass through
        the documents for better efficiency.

        Args:
            is_index_semi_structured: Variable denoting if the index that's is currently being processed is of type SemiStructured
            unsuccessful_docs: A list of documents which were processed unsuccessfully
            documents: List of document dictionaries to process
            
        Returns:
            Tuple containing:
            - List of deduplicated documents
            - Set of unique document IDs
            - Dictionary of document IDs that contain dictionary values and their index in the documents list
        
src/marqo/core/document/document.py