2011-12-21 13 views
8

Hago recursión para encontrar un valor largo dentro de una lista con varios hijos que también pueden tener hijos.Detener la recursión completamente al devolver algo

siguiente método:

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; 
} 

¿Es posible cuando lo haga return td; (véase la Fila comentado) que toda mi recursividad se detiene?

Gracias

+0

No se preocupe, que va a pasar. La recursión se detendrá allí. –

+0

¿Estás seguro de que estás hablando de detener las llamadas recursivas a getTaxonomyData? Si está tratando de evitar el bucle innecesariamente con el foreach porque ya tiene el valor que necesita, entonces lo que tiene que hacer es agregar "break"; justo después de "output = td"; instrucción. Y creo que en este caso un tiempo sería una mejor solución ... –

+0

@Jani: No, la recursividad * no * se detendrá si una llamada profunda simplemente regresa - porque la recursión sería de la cláusula 'else', que ignora el valor de retorno, y simplemente continúa con el siguiente elemento de 'TaxonomyTree'. –

Respuesta

14

que sospechan que desea algo como:

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; 
} 

Cada return sólo devuelve un nivel, pero comprobando el valor de retorno en la cláusula else, podemos regresar todo el camino hasta la pila cuando encontramos el valor correcto

El resultado final devuelto a la persona que llama será una referencia nula si no se ha encontrado.

Tenga en cuenta que he eliminado el parámetro "salida", lo cual no habría sido efectiva de todos modos ya que no era un parámetro ref, y no es tan clara como simplemente usando el valor de retorno.

+0

Eso solo guarda una llamada. y es innecesario en mi humilde opinión. –

+0

Creo que la recursividad de la cola es la solución –

+0

@ Jani: No estoy seguro de a qué se refiere. El código original simplemente no funcionaría, no está usando el resultado de la llamada recursiva. –

1

Una solución de extensión de LINQ que subí, probablemente más lento, pero hay que ir ..

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)); 
    } 
} 
Cuestiones relacionadas