2015-06-18 5 views
2

Мне нужно использовать правила глобализации для поиска всех вхождений строки в документе. Псевдокод:Использование StringComparer с StringBuilder для поиска строки

var searchText = "Hello, World"; 
var compareInfo = new CultureInfo("en-US").CompareInfo; 

DocumentIterator start = null; // the start position if a match occurs 
var sb = new StringBuilder(); 

// the document is not a string, but exposes an iterator to its content 
for (var iter = doc.Start(); iter.IsValid(); ++iter) 
{ 
    start = start ?? iter; // the start of the potential match 

    var ch = iter.GetChar(); 
    sb.Append(ch); 

    if (compareInfo.Compare(searchText, sb.ToString()) == 0) // exact match 
    { 
     Console.WriteLine($"match at {start}-{iter}"); 
     // not shown: continue to search for more occurrences. 
    } 
    else if (!compareInfo.IsPrefix(criteria.Text, sb.ToString())) 
    { 
     // restart the search from the character immediately following start 
     sb.Clear(); 
     iter = start; // this gets incremented immediately 
     start = null; 
    } 
} 

Этот делегат CompareInfo - это сложная задача, связанная с культурой.

Однако потоковый процесс, реализованный кодом, имеет проблемы с производительностью, поскольку он вызывает StringBuilder.ToString() на каждой итерации, тем самым лишившись преимущества производительности StringBuilder.

Вопрос: Как я могу эффективно выполнять поиск?

+0

Почему вы не можете использовать compareInfo.IndexOf (searchText, sb), где sb - полный документ? – Oleg

+0

@Oleg, я отредактировал код, чтобы более четко указать, что документ не является строкой, но предоставляет итератору его содержание символа. – bright

ответ

0

Итак, почему бы не скопировать весь документ в строкоструйную машину сначала, используйте 1 ToString(). Затем просто используйте аналогичную схему для повторения всех возможных значений. Используйте compareInfo.Compare (критерии.Text, 0, criteria.Text.Length, docString, startIndex, checkLength)

+0

Хорошо, поэтому я прочитал комментарий о слишком больших данных, чтобы скопировать в строку все сразу, поэтому просто игнорируйте это. Я думаю, вам нужно будет сделать некоторые chunking, как предложено ниже. Просто выберите произвольный размер для дампа в строку, затем вызовите функцию поиска, как только вы найдете совпадение, вы можете очистить sb и снова начать с нового местоположения. –

0

Почему бы не использовать String IndexOf, который является чувствительным к культуре, а затем перебирает ваш документ с помощью indexOf, чтобы начать следующий поиск до тех пор, пока ничего не будет найдено. См. first answer here.

Все, что вам нужно для начала, это установить текущую культуру. Я предполагаю, что цикл do тогда очевиден.

+0

Документ не является строкой, поэтому я использовал doc [i] в ​​псевдокоде. Я могу прочитать его в одном большом StringBuilder, но это во многих случаях проблематично: a) стоимость памяти; б) итератор на самом деле не является простым целым числом, как я показал - так что мне тоже нужно будет кэшировать их , – bright

+0

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

+0

Как это избежать вызова StringBuilder.ToString() в цикле? Другие проблемы также приходят на ум. Не могли бы вы опубликовать версию кода, который, по вашему мнению, будет работать? Cheers – bright

Смежные вопросы