2010-12-02 9 views
14

Tengo una lista de proyectos y si selecciono un proyecto, daré una opción anterior y siguiente. He agregado un ejemplo de código rápido, pero espero que haya una forma mejor/más rápida de hacerlo, por ejemplo, 500 proyectos.¿Cómo obtener el artículo antes de la corriente y después del actual en una lista con Linq/C#?

¿Existe tal vez una opción de linq o algo así?

He comprobado el enumarator pero eso solo tiene un movimiento. Next en no puede establecer la corriente.

Ejemplo rápido:

proyectos es un diccionario de proyecto

es un KeyValuePair que existe en el diccionario

var match = false; 
var save = new KeyValuePair<ExtendedProjectLightPlan, Page>(); 
var before = new KeyValuePair<ExtendedProjectLightPlan, Page>(); 
var after = new KeyValuePair<ExtendedProjectLightPlan, Page>(); 
foreach (var p in projects) 
{ 
    before = save; 
    save = p; 

    if (match) 
    { 
     after = p; 
     break; 
    } 

    if (p.Key.Id == project.Key.Id) 
    { 
     match = true; 
    }     
} 

Respuesta

13

No hay nada integrado en LINQ para hacer esto, pero podría escribir el suyo con bastante facilidad ... aquí hay una implementación que usa Tuple de .NET 4. Devolverá n-2 elementos para una secuencia que originalmente tiene n elementos - pero podrías ajustar eso si es necesario.

public IEnumerable<Tuple<T, T, T>> WithNextAndPrevious<T> 
    (this IEnumerable<T> source) 
{ 
    // Actually yield "the previous two" as well as the current one - this 
    // is easier to implement than "previous and next" but they're equivalent 
    using (IEnumerator<T> iterator = source.GetEnumerator()) 
    { 
     if (!iterator.MoveNext()) 
     { 
      yield break; 
     } 
     T lastButOne = iterator.Current; 
     if (!iterator.MoveNext()) 
     { 
      yield break; 
     } 
     T previous = iterator.Current; 
     while (iterator.MoveNext()) 
     { 
      T current = iterator.Current; 
      yield return Tuple.Create(lastButOne, previous, current); 
      lastButOne = previous; 
      previous = current; 
     } 
    }   
} 

Tenga en cuenta que según la respuesta de LukeH, los diccionarios están desordenados ... pero espero que lo anterior le ayude de todos modos.

15

¿Ha intentado utilizar IndexOf() y ElementAt() métodos ??

Int32 index = list1.IndexOf(item); 
    var itemPrev = list1.ElementAt(index - 1); 
    var itemNext = list1.ElementAt(index + 1); 
+0

Mi culpa, me refiero a un diccionario. Editado el ejemplo ya – Marco

+1

Con este código obtendrá una excepción si el artículo es el primer elemento, es decir, en el índice 0 o el último. –

+2

@Marco: ¿Qué significa antes y después en un diccionario? ¿Estás usando un ['SortedDictionary'] (http://msdn.microsoft.com/en-us/library/f7fta44c.aspx)? –

5

Los diccionarios no tienen un orden intrínseco, por lo que la idea de elementos anteriores y siguientes es bastante absurda.

1

Estoy de acuerdo con los otros comentarios con respecto a ordenar en diccionarios. Pero dado que los diccionarios ofrecen IEnumerable<KeyValuePair<K, V>>, hay, al menos, un pequeño argumento para decir que tienen algún tipo de orden. De todos modos, aquí está mi sugerencia:

var ll = new LinkedList<ExtendedProjectLightPlan>(); 
var qs = 
    from p in projects 
    let node = ll.AddLast(p.Key) 
    select new { Project = p, Node = node, }; 

var lookup = qs.ToDictionary(q => q.Project, q => q.Node); 

var current = (ExtendedProjectLightPlan)null; //Whatever the current one is. 

var previous = lookup[current].Previous.Value; 
var next = lookup[current].Next.Value; 

Esto debería hacer que sea muy sencillo pasar de cualquier proyecto a la anterior o siguiente - y va a ser muy muy rápido. (A pesar de que la velocidad no debería ser un problema ya que se trata de la interfaz de usuario, ¿verdad?)

14

artículo antes 'current ':

items.TakeWhile(x => x != current).LastOrDefault(); 

artículo después de' current':

items.SkipWhile(x => x != current).Skip(1).FirstOrDefault(); 

funciona bien para tipos integrales pero devolverá default(T) al final de la secuencia. Puede ser útil enviar los elementos al Nullable<T> para que antes del primer artículo, y después del último artículo, devuelva null.

Cuestiones relacionadas