Быстрое сравнение строк со списком

Одинарная кавычка является запуском и концом строки. Точка с запятой является концом оператора. Таким образом, если они делали выбор как это:

Select *
From Students
Where (Name = '<NameGetsInsertedHere>')

SQL стал бы:

Select *
From Students
Where (Name = 'Robert'); DROP TABLE STUDENTS; --')
--             ^-------------------------------^

В некоторых системах, эти select добрался бы, работал сначала сопровождаемый drop оператор! Сообщение: не ВСТРАИВАЙТЕ ЗНАЧЕНИЯ В СВОЙ SQL. Вместо этого используйте параметры!

5
задан Matt Howells 20 July 2009 в 13:25
поделиться

8 ответов

Вы можете использовать trie для хранения списка строк; попытки были разработаны для быстрого re trie val. Вот один из примеров реализации дерева в C #.

Обновление : Презентация PowerPoint по свернутым попыткам для Unicode и Ifo по реализации свернутого дерева для Unicode (не C #)

5
ответ дан 18 December 2019 в 10:48
поделиться

Рассматривали ли вы использование вместо этого класса HashSet (в .NET 3)?

2
ответ дан 18 December 2019 в 10:48
поделиться

Относительно вашей проблемы "когда список невелик"; если вы не против использования неуниверсальных коллекций, System.Collections.Specialized.HybridDictionary сделает что-то вроде этого; он инкапсулирует System.Collections.Specialized.ListDictionary , когда он маленький, или System.Collections.Hashtable , когда он становится больше (> 10 ). Стоит взглянуть?


В противном случае; возможно, вы могли бы использовать HashSet с настраиваемым компаратором? Затем вы можете выбрать, насколько дорого GetHashCode () ...

using System;
using System.Collections.Generic;

class CustomStringComparer : IEqualityComparer<string> {
    public bool Equals(string x, string y) {
        return string.Equals(x, y);
    }
    public int GetHashCode(string s) {
        return string.IsNullOrEmpty(s) ? 0 :
            s.Length + 273133 * (int)s[0];
    }
    private CustomStringComparer() { }
    public static readonly CustomStringComparer Default
        = new CustomStringComparer();
}
static class Program {
    static void Main() {
        HashSet<string> set = new HashSet<string>(
            new string[] { "abc", "def", "ghi" }, CustomStringComparer.Default);
        Console.WriteLine(set.Contains("abc"));
        Console.WriteLine(set.Contains("abcde"));
    }
}
2
ответ дан 18 December 2019 в 10:48
поделиться

Возможно, HybridDictionary здесь лучший вариант. Его внутреннее использование зависит от количества предметов в коллекции.

2
ответ дан 18 December 2019 в 10:48
поделиться

В итоге я сделал следующее:

private static bool Contains(List<string> list, string value)
{
    bool contains = null != list.Find(str => str.ToLower().Equals(value.ToLower()));

    return contains;
}

Я предполагаю, что вы могли бы создать метод расширения для List , но этого было достаточно для моих нужд.

2
ответ дан 18 December 2019 в 10:48
поделиться

Кстати, если память не изменяет, при построении String ее HashValue предварительно вычисляется и сохраняется вместе со строкой в ​​качестве оптимизации для этого типа варианта использования. Если вы используете символьный массив или StringBuilder, это явно не применимо, но для неизменяемой String это должно быть.

РЕДАКТИРОВАТЬ: Я ошибаюсь ... Java кеширует String HashCode, C # - нет.

0
ответ дан 18 December 2019 в 10:48
поделиться

Вы можете использовать интернирование строк сделать это очень быстро. При построении списка вы должны сохранить интернированный формат требуемой строки (результат string.Intern () ). Затем вам нужно сравнить интернированную строку с объектом .ReferenceEquals - поскольку интернированные строки имеют ту же ссылку.

List<string> BuildList() {
    List<string> result;
    foreach (string str from StringSource())
         result.Add(str.Intern());
    return result;
}

bool CheckList(List<string> list, string stringToFind) { // list must be interned for this to work!
    return list.Find(str => object.ReferenceEquals(str, stringToFind)) != null;
}

Это приведет к четырехбайтовому сравнению для каждого списка и одному проходу по исходная строка. Внутренний пул строк построен специально для быстрого сравнения строк и определения, существует ли она уже, поэтому внутренняя операция должна быть довольно быстрой.

0
ответ дан 18 December 2019 в 10:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: