2011-12-21 14 views
8

Effettuo la ricorsione per trovare un valore lungo all'interno di un elenco con più figli che può anche avere figli.Interrompi completamente la ricorsione quando si restituisce qualcosa

seguente metodo:

public TaxonomyData getTaxonomyData(long taxId, List<TaxonomyData> TaxonomyTree, TaxonomyData output) 
{ 
    //find taxid in the taxonomy tree list and return the taxonomydata 

    foreach (TaxonomyData td in TaxonomyTree) 
    { 
     if (td.TaxonomyId == taxId) 
     { 
       output = td; 
       //return td; => when doing a return here means I already found a match so it is not necessary to do all the recursion. 
     } 
     else if (td.Taxonomy.Length > 0) 
     { 
      getTaxonomyData(taxId, td.Taxonomy.ToList(), output); 
     } 
    } 

    return output; 
} 

E 'possibile quando faccio return td; (vedi riga commentato) che tutta la mia ricorsione si ferma?

Grazie

+0

Non preoccuparti, accadrà. La ricorsione si fermerà qui. –

+0

Sei sicuro di voler interrompere le chiamate ricorsive per getTaxonomyData? Se stai cercando di evitare il looping innecesmente con il foreach perché hai già il valore che ti serve, allora ciò che devi fare è aggiungere "break"; subito dopo "output = td;" istruzioni. E penso che in questo caso un po 'di tempo sarebbe una soluzione migliore ... –

+0

@Jani: No, la ricorsione * non si fermerà se viene restituita una chiamata profonda, perché la ricorsione sarebbe dalla clausola 'else', che ignora il valore di ritorno, e continua semplicemente con il prossimo elemento di 'TaxonomyTree'. –

risposta

14

ho il sospetto che si desidera qualcosa di simile:

public TaxonomyData GetTaxonomyData(long taxId, IEnumerable<TaxonomyData> tree) 
{ 
    foreach (TaxonomyData td in tree) 
    { 
     if (td.TaxonomyId == taxId) 
     { 
      return td; 
     } 
     else 
     { 
      // See if it's in the subtree of td 
      TaxonomyData data = GetTaxonomyData(taxId, td.Taxonomy); 
      if (data != null) 
      { 
       return data; 
      } 
     } 
    } 
    // Haven't found it anywhere in this tree 
    return null; 
} 

Ogni return restituisce un solo livello, ma controllando il valore di ritorno nella clausola else, siamo in grado di restituire tutta la strada fino alla pila quando troviamo il giusto valore

Il risultato finale restituito al chiamante sarà un riferimento null se non è stato trovato.

Si noti che ho rimosso il parametro "output", che non sarebbe stata efficace in ogni caso in quanto non era un parametro ref, e non è chiaro come solo utilizzando il valore di ritorno.

+0

Questo salva solo una chiamata. ed è inutile IMHO. –

+0

Penso che la ricorsione in coda sia la soluzione –

+0

@Jani: Non sono sicuro di cosa intendi. Il codice originale semplicemente non funzionerebbe - non utilizza affatto il risultato della chiamata ricorsiva. –

1

una soluzione di estensione LINQ mi si avvicinò con, probabilmente, più lento ma ci si va ..

public static class Ext 
{ 
    public static T SingleOrDefault<T>(this IEnumerable<T> enumerable,Func<T,bool> predicate, Func<T,T> defaultSelector) 
     where T : class 
    { 
     return enumerable.SingleOrDefault(predicate) ?? enumerable.SkipWhile<T>(t=>defaultSelector(t) == null).Select(defaultSelector).SingleOrDefault(); 
    } 

    public static TaxonomyData Get(this IEnumerable<TaxonomyData> tree, int taxId) 
    { 
     return tree.SingleOrDefault(t=> t.TaxonomyId == taxId,t=>t.Taxonomy.Get(taxId)); 
    } 
} 
Problemi correlati