Вопрос по c#, regex, linq – Количество вхождений символа в строку [дубликаты]

89

На этот вопрос уже есть ответ:

Как бы вы посчитали вхождения строки (на самом деле символ) внутри строки? 29 ответов

Я пытаюсь получить количество вхождений определенного символа, например& в следующей строке.

string test = "key1=value1&key2=value2&key3=value3";

Как определить, что в указанной выше переменной тестовой строки есть 2 амперсанда (&)?

Почему регулярное выражение ?????? CodesInChaos
@ CodeInChaos Поскольку некоторые люди, сталкиваясь с проблемой, думают: «Я знаю, я буду использовать регулярные выражения». Tanzelax
@ Tanzelax.Как это ? : -) gdoron
Больше забавных ответовВо хотя они обрабатывают символыа такж строки в строках. Тесты и т. Д. Включены. ruffin
'Очевидно, что НЕ дубликат, так как этот пост хочет считать символ, а не строку. Несмотря на это, следует отметить, что большинство ответов в сообщении, включая принятый, НЕПРАВИЛЬНЫ. (В том смысле, что они не учитывают появление строки, а только символы.) Неправильно + неправильно = правильно, но все же это одно из самых темных и смущающих мест SO .. TaW

Ваш Ответ

6   ответов
204

Ты мог бы сделать это:

int count = test.Split('&').Length - 1;

Или с LINQ:

test.Count(x => x == '&');
Стоит отметить, что первый подход может быть невероятно дорогим, если строка длинная. В худшем случае, если строка большая и (почти) целиком состоит из повторяющихся разделителей (&), она может выделить 12-24x первоначальный размер строки из-за накладных расходов объекта в .Net. Я бы пошел со вторым подходом, и если это не достаточно быстро, то написать цикл for. Niall Connaughton
24

Потому чтоLINQ может сделать все ...:

string test = "key1=value1&key2=value2&key3=value3";
var count = test.Where(x => x == '&').Count();

Или, если хотите, можете использоватьCount перегрузка, которая принимает предикат:

var count = test.Count(x => x == '&');
LINQ тожепомедленне делать все. Проверьте эту веб-страницу для тестов если хочешьбыстр код. Free Coder 24
@ FreeCoder24 это не проблема LINQ, а скорее плохой компилятор. Например. пример должен быть встроен в простой цикл (как в C ++ и Haskell). Hi-Angel
@ FreeCoder24, так же, как C # медленнее, чем Assembly во всем. Если хочешьбыстр код, используйте сборку. И, кстати, LINQ быстрее сортирует, чем «родные» методы фреймворка. gdoron
12

е:

int cnt = 0;
foreach (char c in test) {
  if (c == '&') cnt++;
}

Вы можете использовать расширения Linq, чтобы сделать более простую и почти эффективную версию. Есть немного больше накладных расходов, но это все еще удивительно близко к циклу в производительности:

int cnt = test.Count(c => c == '&');

Тогда есть староеReplace трюк, однако он лучше подходит для языков, где циклы неуклюжи (SQL) или медленны (VBScript):

int cnt = test.Length - test.Replace("&", "").Length;
Удивительно близко к циклу в производительности только с довольно маленькими стогами сена. TaW
@ TaW: я не вижу значительной разницы в скорости между короткими и длинными (1 МБ) строками, но по какой-то причине в режиме x64 разница больше, чем в режиме x86. Guffa
Я не проверял версию счетчика символов, но счет строк linq все больше и больше замедляется с более длинными строками и, наконец, умирает с исключением oom. 1МБ пока не проблема. TaW
@ PawelCioch: чем длиннее строка, тем она будет медленнее. Не существует волшебного способа обработки всей строки без обработки всей строки. Guffa
@ PawelCioch: Должно быть что-то не так с вашим тестом производительности.Replace, Split илиIndexOf не может быть быстрее, чем обход строки и проверка каждого символа, поскольку это именно то, что они делают, только добавляя дополнительные издержки. Guffa
9

Зачем использовать для этого регулярное выражение?String реализуетIEnumerable<char>, так что вы можете просто использовать LINQ.

test.Count(c => c == '&')
8

обратите внимание, что HttpContext имеет некоторую помощь для вас

int numberOfArgs = HttpContext.Current.QueryString.Count;

Подробнее о том, что вы можете сделать с помощью QueryString, смотрите в NameValueCollection

6

е словарь, который содержит пары ключ-значение в качестве бонуса.

string test = "key1=value1&key2=value2&key3=value3";

var keyValues = Regex.Matches(test, @"([\w\d]+)=([\w\d]+)[&$]*")
                     .Cast<Match>()
                     .ToDictionary(m => m.Groups[1].Value, m => m.Groups[2].Value);

var count = keyValues.Count - 1;
haha, "самый неэффективный способ", люби это! payo
Поместите это как Q & A с меткойcode-trolling на Codegolf.stackexchange.com Kroltan

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