All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.deephaven.lang.completion.results.FuzzyList Maven / Gradle / Ivy

There is a newer version: 0.37.0
Show newest version
//
// Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending
//
package io.deephaven.lang.completion.results;

import io.deephaven.web.shared.fu.MappedIterable;
import org.apache.commons.text.similarity.FuzzyScore;
import org.jetbrains.annotations.NotNull;

import java.util.Iterator;
import java.util.Locale;
import java.util.TreeSet;

/**
 * A list-like object that performs fuzzy sorting on the edit distance of strings.
 *
 * The constructor takes the pattern String (user input), then you can add-by-string-key any number of objects of type
 * T. The score for each String is used to sort entries which contain source object and string key.
 *
 * This can allow you to, for example, sort methods based on distance to a user-entered search query.
 */
public class FuzzyList implements Iterable {

    private static final FuzzyScore scorer = new FuzzyScore(Locale.US);

    private class FuzzyEntry implements Comparable {
        final String result;
        final T value;
        final double score;

        private FuzzyEntry(String key, T value, double score) {
            this.result = key;
            this.value = value;
            this.score = score;
        }

        @Override
        public int compareTo(@NotNull FuzzyEntry o) {
            if (score == o.score) {
                int myDiff = Math.abs(result.length() - query.length());
                int yourDiff = Math.abs(o.result.length() - query.length());
                if (myDiff == yourDiff) {
                    // length and score is the same, use string comparisons.
                    // If the strings are equal, then we are quite fine w/ discarding duplicates.
                    return result.compareTo(o.result);
                }
                // lowest difference in length wins
                return myDiff < yourDiff ? -1 : 1;
            }
            // highest score wins
            return score > o.score ? -1 : 1;
        }

        private T getValue() {
            return value;
        }
    }

    private final TreeSet entries;
    private final String query;

    public FuzzyList(String key) {
        this.query = key;
        entries = new TreeSet<>();
    }

    public void add(String key, T item) {
        final Integer score = scorer.fuzzyScore(this.query, key);
        // Later: add extra points for matches that have been used before.
        FuzzyEntry entry = new FuzzyEntry(key, item, score);
        entries.add(entry);
    }

    @NotNull
    @Override
    public Iterator iterator() {
        return MappedIterable.of(entries).mapped(FuzzyEntry::getValue).iterator();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy