2010-10-24 5 views
1

J'essaie d'écrire une fonction en ligne pour les occurrences de comptage d'un mot dans une chaîne en utilisant des expressions lambda récursivement.Tout suggérer de stocker une valeur dans une expression lambda

La fonction:

Func<string, string, int> getOccurrences = null; 
getOccurrences = (text, searchTerm) => 
    text.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase) == -1 
    ? 0 
    : getOccurrences(
     text.Substring(
     text.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase) 
     + searchTerm.Length), 
     searchTerm) + 1; 

Le problème est que je suis deux fois appel méthode IndexOf, Le premier est pour la condition de rupture récursive et le second est d'obtenir la valeur pour l'ajouter.

Y at-il une suggestion pour l'appeler une fois?

Merci d'avance.

+1

Cela ne fonctionnerait-il pas simplement d'utiliser une regex pour cela, peut-être quelque chose comme \ b (search_term) \ b. Est-ce que je manque quelque chose? –

+0

Est-ce un exercice? Est-ce que vous essayez de faire autre chose, et c'est un échantillon non représentatif? Voulez-vous l'utiliser dans le code de production? – outis

+0

Si ce n'est déjà fait, donnez une lecture à ["Expressions lambda récursives"] (http://blogs.msdn.com/b/madst/archive/2007/05/11/recursive-lambda-expressions.aspx). – outis

Répondre

6

Si vous n » À l'esprit un lambda non-pure-fonction que vous pouvez faire: -

Func<string, string, int> getOccurrences = null; 
getOccurrences = (text, searchTerm) => 
{ 
    int i = text.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase); 
    return i == -1 ? 0 : getOccurrences(i + searchTerm.Length), searchTerm) + 1; 
} 
+0

Qu'est-ce qui est "non-pur" à ce sujet? (Je n'ai plus de votes :-) Cela montre simplement qu'un "non-lambda" (par exemple plusieurs lignes dans une fonction-anon/délégué) est une approche parfaitement bonne (sinon meilleure) qu'une "lambda pure". Je crois qu'ils sont tous les deux compilés de la même manière, mais ils n'ont pas vérifié cela. –

+0

pst: C'est "non pur" dans le sens où c'est un lambda que vous ne pouvez pas transformer en une expression > ' – Gabe

+0

@Highttech: entre les accolades, est-ce comme un délégué , puis? – IAbstract

0

Je vous suggère de faire une méthode distincte

Func<string, string, int> getOccurrences = GetOccurrences; 

    private int GetOccurrences(string text, string searchTerm) 
    { 
     //...  
    } 

ou en ligne

Func<string, string, int> getOccurrences = delegate(string text, string searchTerm) 
              { 
               //... 
              }; 

avec la syntaxe lambda, mais juste une autre façon d'écrire le

ci-dessus
Func<string, string, int> getOccurrences = (string text, string searchTerm) => 
              { 
               //... 
              }; 
0

Vous pouvez le faire comme ceci:

Func<string, string, int> getOccurrences = 
    (text, searchTerm) => getOccurrencesInternal(
     text, 
     searchTerm, 
     text.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase)); 
Func<string, string, int, int> getOccurrencesInternal = null; 
getOccurrences = (text, searchTerm, index) => 
    index == -1 
    ? 0 
    : getOccurrencesInternal( 
     text.Substring( 
     index + searchTerm.Length), 
     searchTerm) + 1; 
0

Vous pouvez utiliser un lambda supplémentaire, anonyme et appeler immédiatement. Je ne suis pas certain de la syntaxe exacte C#, mais il devrait ressembler à:

Func<string, string, int> getOccurrences = null; 
getOccurrences = (text, searchTerm) => 
    ((index) => 
    index == -1 
    ? 0 
    : getOccurrences(text.Substring(index + searchTerm.Length), 
     searchTerm) + 1 
)(text.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase)) 
0

Ma solution habituelle à ce genre de problèmes, sans tenir compte des optimisations, est juste pour supprimer le terme correspondant et vérifier tout changement la longueur de la chaîne résultante.

Func<String, String, Int32> getOccurrences = (text, term) => 
    (text.Length - text.Replace(term, "").Length)/term.Length; 
Questions connexes