2013-07-01 23 views
0

我想.NET實施LINQ以下算法(C#優選):如何使用LINQ通過元音處理字符串列表?

  1. 輸入是任意字符串。字符串的第一個字符保證是元音字母。例如。 "alkjihgefdcb"

  2. 將字符串分解爲由元音分隔的塊。例如。 "alkj","ihg","efdcb"

  3. 按字母順序對每個塊進行排序。例如。 "ajkl""ghi""bcdef"

  4. 將塊加回到一起以產生輸出字符串。例如。 "ajklghibcdef"

有一種優雅的(即純粹的功能)的方式來做到這一點?第3步和第4步很容易,但我很難步驟2,這似乎需要與SelectMany相反的東西。謝謝。

編輯:我很欣賞正則表達式的解決方案,但我正在尋找一種純粹基於LINQ的方法。在我的實際應用中,這些字符串是域對象的列表,所以正則表達式不太適用。

+0

你介意一個額外的擴展方法嗎?如果沒有,請查看我的答案。 –

+0

你打算如何處理這樣一個事實,即「y」可以根據上下文有條件地成爲元音?假裝永遠是,假裝永遠不會,或者試圖根據非單詞的背景來判斷? – Servy

回答

1

您可以使用LINQ和Regular Expressions

string.Join(
    string.Empty, 
    Regex.Matches("alkjihgefdcb", "[aeiou][^aeiou]+") 
     .Cast<Match>() 
     .Select(m => string.Join(string.Empty, m.Value.OrderBy(c => c)))); 
// ajklghibcdef 

或者更好的是:

string.Join(
    string.Empty, 
    Regex.Split("alkjihgefdcb", "(?=[aeiou])") 
     .Select(m => string.Join(string.Empty, m.OrderBy(c => c)))); 
// ajklghibcdef 

使用純的Linq:

var i = 0; 
string.Join(
    string.Empty, 
    "alkjihgefdcb".GroupBy(c => "aeiou".IndexOf(c) == -1 ? i : ++i) 
        .SelectMany(g => g.OrderBy(c => c))); 
// ajklghibcdef 

雖然我毫不猶豫地真正調用功能,因爲它依靠i正在更新的GroupBy方法的副作用。

+0

出於興趣,爲什麼'Skip(1)'? –

+0

,因爲正則表達式會留空,因爲前面匹配的是元音 –

+0

@newStackExchangeInstance它始終以元音開頭,所以第一個字符串將爲空。我想這是沒有必要的,因爲它會在最後的加入中掉下來。 –

2

當然。

Regex.Split(input, @"(?=[aeiou])").Where(s => !string.IsNullOrWhiteSpace(s)) 
    .OrderBy(n => n).Aggregate((a, b) => a + b); 

如果你不想使用正則表達式,我們需要一個擴展方法:

public static IEnumerable<IEnumerable<T>> SplitOn<T>(this IEnumerable<T> source, params T[] splitObjs) 
{ 
    //appropriate error checking, check for null etc 
    if (!source.Any() || !splitObjs.Any()) return new[]{source}; 
    List<T> buffer = new List<T>() 
    foreach (T item in source) 
    { 
     if (splitObjs.Contains(item) && buffer.Any()) 
     { 
      yield return buffer; 
      buffer.Clear(); 
     } 
     buffer.Add(item); 
    } 
    if (buffer.Any()) yield return buffer; 
} 

然後它應該是簡單的:

input.SplitOn('a', 'b', 'c', 'd', 'e').Select(s => new string(s.ToArray())) 
    .OrderBy(n => n).Aggregate((a, b) => a + b); 
0

這裏使用LINQ(純功能方式)的單線解決方案。這個想法是用#代替所有元音,然後分割#

string input = "alkjihgefdcb"; 

input = input 
.Replace("a","#a") 
.Replace("e","#e") 
.Replace("i","#i") 
.Replace("o","#u") 
.Replace("u","#u") 
.Split(new char[]{'#'},StringSplitOptions.RemoveEmptyEntries) 
.Select (i => new string(i.ToCharArray().OrderBy (x => x).ToArray())) 
.Aggregate ((a,b) => a + b); 
+0

對不起!該行.Replace(「o」,「#u」)應該是.Replace(「o」,「#o)這是一個拼寫錯誤。 – sudipta

+0

'Aggregate'可以被'string.Concat'的調用取代將顯着提高效率,Aggregate會創建一大堆不需要的中間字符串,並花費大量時間在它們之間複製相同的字符。 – Servy

相關問題