Как отсортировать результат linq по наибольшему сходству / равенству - PullRequest
2 голосов
/ 16 апреля 2010

Я хочу выполнить поиск музыкальных инструментов, в котором есть информация Имя, категория и происхождение, как я и просил в моем сообщении .

Но теперь я хочу отсортировать / сгруппировать результат по сходству / равенству с таким ключевым словом, как. Если у меня есть список

{барабан, рояль, гитара, гитара, арфа, фортепиано} << отсортировано по названию </p>

и если я запросил "p", результат должен быть {Piano, Grand Piano, Harp}
но сначала он показывает арфу из-за последовательности списка источников

и если я добавлю {Grand Piano} в список и запросю "фортепиано"
результат будет похож на {Piano, Grand Piano}
или запрос "гитара" это должно быть {Guitar, Guitarrón}

вот мой код

static IEnumerable<MInstrument> InstrumentsSearch(IEnumerable<MInstrument> InstrumentsList, string query, MInstrument.Category[] SelectedCategories, MInstrument.Origin[] SelectedOrigins)
{
    var result = InstrumentsList
        .Where(item => SelectedCategories.Contains(item.category))
        .Where(item => SelectedOrigins.Contains(item.origin))
        .Where(item =>
            {
                if (
                        (" " + item.Name.ToLower()).Contains(" " + query.ToLower())
                        || item.Name.IndexOf(query) != -1
                    )
                {
                    return true;
                }
                return false;
            }
        )
        .Take(30);

    return result.ToList<MInstrument>();
}

Или результат может быть похож на мой старый алгоритм, изобретенный самим собой , который я назвал "по порядку появления",
это просто нормально для меня.

И дальнейшие действия - поиск имени, категории или происхождения, например.
Если я наберу "Италия", то должен найти Piano или что-то из Италии.
Или, если я наберу "string", он должен найти Guitar.

Есть ли способ сделать это, пожалуйста, скажите мне.

Заранее спасибо.

1 Ответ

5 голосов
/ 16 апреля 2010

Вы хотите OrderBy / OrderByDescending -

result = InstrumentsList.
     .Where(...)
     .OrderByDescending(instrument => 
         StringSimilarityScore(instrument.Name, searchString))
     .Take(30);

Что касается определения StringS SimilarityScore - лучше всего использовать нечеткое совпадение, но вы можете начать с количественного определения совпадения на основе доли имени, сопоставляемого строкой поиска:

double StringSimilarityScore(string name, string searchString)
{
    if (name.Contains(searchString))
    {
        return (double)searchString.Length / (double)name.Length;
    }

    return 0;
}

Возможно, вы захотите рассмотреть положение строки поиска в имени (чем раньше, тем лучше) для случаев, когда указана одна буква, но я оставлю это на ваше усмотрение. : -)

...