2010-11-05 10 views

Respuesta

3

Similar a la respuesta de svick, excepto con efectos secundarios para evitar las desventajas e inversa:

int[] source = new int[] { 1, 2, 3, 4, 4, 4, 5, 6, 7, 4, 4, 4, 8, 9, 4, 4, 4 }; 

List<int> result = new List<int> { source.First() }; 
source.Aggregate((acc, c) => 
    { 
     if (acc != c) 
      result.Add(c); 
     return c; 
    }); 

Editar: Ya no necesita la source.First() como por la preocupación de mquander:

int[] source = new int[] { 1, 2, 3, 4, 4, 4, 5, 6, 7, 4, 4, 4, 8, 9, 4, 4, 4 }; 

List<int> result = new List<int>(); 
result.Add(
    source.Aggregate((acc, c) => 
    { 
     if (acc != c) 
      result.Add(acc); 
     return c; 
    }) 
); 

pienso Todavía me gusta más la solución de Danny.

+0

Estaría en toda esta solución, excepto que el .First inicial() lo mata por operar en cualquier secuencia perezosa. – mquander

+0

Es cierto, hmm ...... –

+0

Ahí vamos, échale un vistazo ahora: D –

5

En realidad no. Me gustaría escribir esto:

public static IEnumerable<T> RemoveDuplicates(this IEnumerable<T> sequence) 
{ 
    bool init = false; 
    T current = default(T); 

    foreach (var x in sequence) 
    { 
     if (!init || !object.Equals(current, x)) 
      yield return x; 

     current = x; 
     init = true; 
    } 
} 
+2

1, pero yo preferiría un mejor nombre para el método '... RemoveDuplicates' es confuso porque parece que implica que todos los duplicados se eliminan, cuando se eliminan los duplicados en realidad sólo * * adyacentes. Tal vez algo así como 'RemoveAdjacentDuplicates' –

+0

No estoy en desacuerdo. Creo que hay un nombre usual para esta operación que no puedo invocar ahora mismo. – mquander

+0

'RemoveRepeats'? –

1

Puede utilizar Aggregate() (aunque no estoy seguro de si es mejor que la solución no LINQ):

var ints = new[] { 1, 2, 3, 4, 4, 4, 5, 6, 7, 4, 4, 4, 8, 9, 4, 4, 4 }; 

var result = ints.Aggregate(
    Enumerable.Empty<int>(), 
    (list, i) => 
     list.Any() && list.First() == i 
     ? list 
     : new[] { i }.Concat(list)).Reverse(); 

I piensan es O (n), pero no estoy del todo seguro.

+1

creativo, pero difícilmente legible ... –

+0

Probablemente la más fiel al estilo funcional, sin embargo. En F # que sería algo así como 'enteros |> List.fold (divertido (L, I) c -> si c <> i después (c :: l, c) otro (l, c)) ([], ints.Head + 1) |> fst |> List.rev'. Ahora, si hay una forma de usar 'yield' u otra forma de comprensión de listas, estamos en el negocio. –

0

Si está utilizando .NET 4, puede hacerlo utilizando el método Zip incorporado, aunque probablemente preferiría usar un método de extensión personalizado como el que se muestra en mquander's answer.

// replace "new int[1]" below with "new T[1]" depending on the type of element 
var filtered = original.Zip(new int[1].Concat(original), 
          (l, r) => new { L = l, R = r }) 
         .Where((x, i) => (i == 0) || !object.Equals(x.L, x.R)) 
         .Select(x => x.L); 
+0

Debe ser 'Pasar (1)', 'no Tome (1)' ... –

+0

@Thomas: No, 'Take (1)' es lo que quería decir. El uso de 'Skip' en su lugar se rompería cuando hay duplicados al comienzo de la secuencia, por ejemplo' {1, 1, 2} '. – LukeH

+0

Tienes razón, me perdí la parte de concatenación, así que pensé que sólo volvería 1 artículo –

4

Sí hay! Código de una línea y un bucle de la matriz.

int[] source = new int[] { 1, 2, 3, 4, 4, 4, 5, 6, 7, 4, 4, 4, 8, 9, 4, 4, 4 }; 
var result = source.Where((item, index) => index + 1 == source.Length 
          || item != source[index + 1]); 

Y de acuerdo a @ consejos de Hogan, que puede ser mejor:

var result = source.Where((item, index) => index == 0 
          || item != source[index - 1]); 

más legible ahora pienso. Significa "elegir el primer elemento y aquellos que no son iguales al anterior".

+0

1: Buena solución. Menos legible que una solución que no sea LINQ, pero LINQ es lo que solicitó OP, y esta es probablemente la solución más legible basada en LINQ. –

+0

Gracioso, de hecho creo que es más legible. –

+0

Esto supone que la colección fuente es una matriz, y este es un problema trivial para resolver cuando tiene acceso indexado y una propiedad 'Longitud'. ¿Qué tal una solución que funciona en cualquier 'IEnumerable ' en su lugar? (Después de todo, la pregunta habla de una secuencia, no de una lista o de una matriz.) – LukeH

Cuestiones relacionadas