2014-02-20 3 views
8

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

Я попытался следующий код Linq

string[] strArray = new string[] { "cello", "guitar", "violin"}; 
string[] vowels = new string[] { "a", "e", "i", "o", "u" }; 

var vNovowels = from vitem in strArray 
       from vowel in vowels 
       where vitem.Contains(vowel) 
       select vitem.Replace(vowel, ""); 

foreach (var item in vNovowels) 
{ 
    Console.WriteLine(item); 
} 

Но я не получаю ожидаемого.

выход я получаю с выше запроса: -

cllo 
cell 
guitr 
gutar 
gitar 
voln 
vilin 

Желаемый результат:

cll 
gtr 
vln 
+0

Это не лямбда-выражение, это запрос LINQ. – TypeIA

+1

@OndrejJanacek Это запрос. Он не пытается изменить существующую коллекцию, но создает новую, основанную на значениях из исходной коллекции. Если это было не так, тогда не было бы смысла иметь операцию проецирования типа 'select'. – Dirk

ответ

7

Хотя Yaakov's reg-ex solution гораздо лучше с точки зрения изящества и эффективности, вы можете использовать Where ради обучения:

string[] strArray = new string[] { "cello", "guitar", "violin" }; 
var vowels = new HashSet<char>("aeiou"); // or: { 'a', 'e', 'i', 'o', 'u' }; 

var vNovowels2 = from vitem in strArray 
       select new string(vitem.Where(c => !vowels.Contains(c)).ToArray()); 

foreach (var item in vNovowels2) 
{ 
    Console.WriteLine(item); 
} 
+0

Я бы подумал, что «HashSet» будет более эффективным, чем регулярное выражение. Я думаю, что твоя элегантность тоже! – Sam

+1

@ Сейм я ценю. Чтобы проверить скорость, я быстро (и примитивно) сравнивал шахту и Яакова, запуская ее миллион раз каждый с секундомером, и оказалось, что рег-ex-подход занимает примерно 38% времени, когда я занимаюсь ... –

+1

FYI: Я добавил некоторые критерии [мой ответ] (http://stackoverflow.com/a/21903029/51) –

13

Вы можете выполнить очень эффективно с использованием регулярных выражений, чтобы соответствовать всем гласным и заменить их пустыми строки:

var strArray = new List<string> { "cello", "guitar", "violin" }; 
var pattern = @"[aeiou]"; 
var noVowels = strArray.Select(item => 
        Regex.Replace(item, pattern, "", RegexOptions.IgnoreCase)); 
foreach (var item in noVowels) {   
    Console.WriteLine(item); 
} 

Это возвращает результаты, которые вы ищете.

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

Update: Я сделал некоторые базовые бенчмаркинга этого решения по сравнению с Mathias' HashSet<char> based solution (benchmark code here), в том числе как компилировать и Noncompiled версий версии Regex. Я побежал против массива 2582 Lorem-Ipsum слов, итерация 10 миллионов раз против множества (так происходит в ~ 25 миллиардов слов), запустив его в LINQPad, беря среднее из 3-х серий:

    Init Each Time    Init One Time 
       avg ms  % diff   avg ms  % diff 
Regex   586   +1%   586   - 
Regex Compiled 581   -    593   +1% 
HashSet   2550  +339%   641  +10% 

It оказывается, что если вы только инициализируете HashSet и шаблон string один раз, то они имеют очень схожую производительность. Regex превосходит Hashset, но только едва (80 мс быстрее, чем 25 миллиардов слов) и Regex Compiled and Noncompiled выполняет почти тождественно. Однако, если вы инициализируете HashSet каждый раз, когда вы запускаете его, он убивает производительность для подхода HashSet.

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

+0

** Почему ** пытаться заменить, если гласный не существует? –

+1

+1 для фактического указания того, что было не так. – Sam

+0

@RoyiNamir Почему явным образом проверяю, существует ли гласная, если Regex.Replace это делает? – Dirk

1

Regex Replace - лучший способ сделать это.

string[] strArray = new string[] { "cello", "guitar", "violin" }; 

var rx = new Regex("^a|e|i|o|u", RegexOptions.IgnoreCase); 

var vNovowels = from vitem in strArray 
       select rx.Replace(vitem, string.Empty); 

foreach (var item in vNovowels) 
{ 
    Console.WriteLine(item); 
} 
Смежные вопросы