private populateCompositeEntity()

in packages/extensions/luis/client/src/Adapters/RecognizerResultAdapter.tsx [183:251]


  private populateCompositeEntity(
    compositeEntity: CompositeEntity,
    entities: Entity[],
    entitiesAndMetadata: any,
    verbose: boolean
  ): Entity[] {
    const childrenEntites: any = verbose ? { $instance: {} } : {};
    let childrenEntitiesMetadata: any = {};

    // This is now implemented as O(n^2) search and can be reduced to O(2n) using a map as an optimization if n grows
    const compositeEntityMetadata: Entity | undefined = entities.find(entity => {
      // For now we are matching by value, which can be ambiguous if the same composite entity
      // shows up with the same text multiple times within an utterance, but this is just a
      // stop gap solution till the indices are included in composite entities
      return entity.type === compositeEntity.parentType && entity.entity === compositeEntity.value;
    });

    const filteredEntities: Entity[] = [];
    if (verbose && compositeEntityMetadata) {
      childrenEntitiesMetadata = this.getEntityMetadata(compositeEntityMetadata);
      childrenEntitiesMetadata.$instance = {};
    }

    // This is now implemented as O(n*k) search and can be reduced to O(n + k)
    // using a map as an optimization if n or k grow
    const coveredSet = new Set();
    compositeEntity.children.forEach(childEntity => {
      for (let i = 0; i < entities.length; i++) {
        const entity = entities[i];
        if (
          !coveredSet.has(i) &&
          childEntity.type === entity.type &&
          compositeEntityMetadata &&
          entity.startIndex !== undefined &&
          compositeEntityMetadata.startIndex !== undefined &&
          entity.startIndex >= compositeEntityMetadata.startIndex &&
          entity.endIndex !== undefined &&
          compositeEntityMetadata.endIndex !== undefined &&
          entity.endIndex <= compositeEntityMetadata.endIndex
        ) {
          // Add to the set to ensure that we don't consider the same child entity more than once per composite
          coveredSet.add(i);
          this.addProperty(childrenEntites, this.getNormalizedEntityType(entity), this.getEntityValue(entity));

          if (verbose) {
            this.addProperty(
              childrenEntites.$instance,
              this.getNormalizedEntityType(entity),
              this.getEntityMetadata(entity)
            );
          }
        }
      }
    });

    // filter entities that were covered by this composite entity
    for (let i = 0; i < entities.length; i++) {
      if (!coveredSet.has(i)) {
        filteredEntities.push(entities[i]);
      }
    }

    this.addProperty(entitiesAndMetadata, compositeEntity.parentType, childrenEntites);
    if (verbose) {
      this.addProperty(entitiesAndMetadata.$instance, compositeEntity.parentType, childrenEntitiesMetadata);
    }

    return filteredEntities;
  }