2010-10-18 3 views
2

J'essaie de transformer une chaîne de mots commençant par une lettre majuscule. Je veux séparer chaque mot avec un espace et ne conserver que la première lettre majuscule. Toutes les autres lettres doivent être en minuscules. Par exemple, "TheQuickBrownFox" deviendrait "The quick brown fox".LINQ façon de transformer "TheQuickBrownFox" en "Le renard brun rapide"

Évidemment, je pourrais utiliser un simple foreach et construire une chaîne en vérifiant chaque caractère, mais j'essaye de le faire en utilisant LINQ.

Savez-vous comment résoudre cela élégamment en utilisant LINQ?

Nous vous remercions de votre aide.

+7

Comment devrait-elle transformer "TheQuickLINQStatement"? –

+1

Vous avez un marteau à la recherche d'un clou? – jason

+0

@Fredrik Mörk Heureusement, cette situation n'apparaîtra jamais :) –

Répondre

7

Vous pouvez diviser les mots en utilisant une expression régulière (et peu LINQ):

public string SplitAsWords(string original) 
{ 
    var matches = Regex.Matches(original, "[A-Z][a-z]*").Cast<Match>(); 
    var str = string.Join(" ", matches.Select(match => match.Value)); 
    str = str[0] + str.Substring(1).ToLower(); 
    return str; 
} 

Un exemple d'utilisation :

[Test] 
public void Example() 
{ 
    string str = SplitAsWords("TheQuickBrownFox"); 
    Assert.That(str, Is.EqualTo("The quick brown fox")); 
} 

Une autre mise en oeuvre en utilisant l'expression régulière peut être (sans LINQ):

public string SplitAsWords(string original) 
{ 
    var str = Regex.Replace(original, "[a-z][A-Z]", 
     new MatchEvaluator(match => match.Value.ToLower().Insert(1, " "))); 

    return str; 
} 
+0

J'accepte votre réponse parce que c'est agréable et propre. Je vous remercie! –

1

Cela ne sera pas idéal pour des situations telles que "PaulTookTheSAT" ou "McDonald'sIsNasty".

string input = "TheQuickBrownFox"; 
string output = input.Select((c, i) => i == 0 ? c.ToString() : char.IsUpper(c) ? " " + c.ToString().ToLower() : c.ToString()).Aggregate((a,b) => a + b); 

Modifier: Utilisation (la plupart du temps) la syntaxe d'expression de requête

string output = (from item in input.Select((c,i) => new { c, i }) 
       let x = item.i == 0 
          ? item.c.ToString() 
          : (char.IsUpper(item.c) ? " " + item.c.ToString().ToLower() : item.c.ToString()) 
       select x).Aggregate((a, b) => a + b); 
1
string s = "TheQuickBrownFox"; 
string transformed = s.Aggregate(new StringBuilder(), (sb, c) => 
    Char.IsUpper(c) && sb.Length > 0 ? sb.AppendFormat(" {0}", Char.ToLower(c)) : sb.Append(c)).ToString(); 
0

Avec System.Text.RegularExpressions.Regexp

System.Text.RegularExpressions.Regex.Split("TheQuickBrownFox","([A-Z][^A-Z]+)").Where(s=>s!=""); 
0

Comment cela?

 string phrase = "TheQuickBrownFox"; 

     var invalidChars = from ch in phrase 
          where char.IsUpper(ch) 
          select ch; 

     foreach (char ch in invalidChars) 
     { 
      int index = phrase.IndexOf(ch); 

      phrase = phrase.Remove(index, 1); 
      phrase = phrase.Insert(index, " " + ch); 
     } 

     Console.WriteLine(phrase); 
     Console.ReadLine(); 
+0

Les index ne deviendront-ils pas obsolètes après la première insertion dans la boucle foreach? –

+0

Oui, si vous le souhaitez, vous pouvez également sélectionner uniquement le caractère, puis appeler un IndexOf dans la boucle foreach. –

0

Linq a été conçu dans un style fonctionnel. L'utiliser de manière impérative ne se retrouverait pas dans un code élégant. Donc, ne pas transformer après la requête, mais dans la requête - mettre la logique dans la section de projection (sélectionnez). (Tout comme la réponse d'Anthony)

var str = (from i in Regex.Split("TheQuickBrownFox", "") 
       select Regex.IsMatch(i, "[A-Z]") ? " " + i : i) 
       .Aggregate((str1, str2) => str1 + str2); 

     Console.WriteLine(str); 
Questions connexes