Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Eliminate consecutive duplicates of list elements

Tags:

c#

list

Is there a "nice" way to eliminate consecutive duplicates of list elements?

Example:

["red"; "red"; "blue"; "green"; "green"; "red"; "red"; "yellow"; "white"; "white"; "red"; "white"; "white"]  

should become

["red"; "blue"; "green"; "red"; "yellow"; "white"; "red"; "white"] 

--By "nice" I mean most readable and understandable to a new user and fast execution :)

like image 268
Wolfy Avatar asked Apr 20 '11 11:04

Wolfy


People also ask

How do you remove repeating elements from a list?

Remove duplicates from list using Set. To remove the duplicates from a list, you can make use of the built-in function set(). The specialty of set() method is that it returns distinct elements. We have a list : [1,1,2,3,2,2,4,5,6,2,1].

How do you remove two consecutive elements from a list in Python?

Using the groupby function, we can group the together occurring elements as one and can remove all the duplicates in succession and just let one element be in the list. This function can be used to keep the element and delete the successive elements with the use of slicing.


2 Answers

A simple and very readable solution:

List<string> results = new List<string>(); foreach (var element in array) {     if(results.Count == 0 || results.Last() != element)         results.Add(element); } 
like image 126
Simon Bartlett Avatar answered Sep 30 '22 13:09

Simon Bartlett


You can roll your own, linq-style.

// For completeness, this is two methods to ensure that the null check  // is done eagerly while the loop is done lazily. If that's not an issue,  // you can forego the check and just use the main function.  public static IEnumerable<T> NonConsecutive<T>(this IEnumerable<T> input) {   if (input == null) throw new ArgumentNullException("input");   return NonConsecutiveImpl(input); }  static IEnumerable<T> NonConsecutiveImpl<T>(this IEnumerable<T> input) {    bool isFirst = true;    T last = default(T);    foreach (var item in input) {       if (isFirst || !object.Equals(item, last)) {           yield return item;           last = item;           isFirst = false;       }    } } 

And use as

array.NonConsecutive().ToArray() 

The advantage is that it's lazily evaluated, so you can use it on any enumeration without having to consume it in its entirety, and chain it with other linq methods (eg: array.Where(i => i != "red").NonConsecutive().Skip(1).ToArray()). If you don't have that requirement and you just want to work with arrays, something like Simon Bartlett's solution might be slightly more performant.

For more information on why it has to be two methods, see here

like image 34
Alex J Avatar answered Sep 30 '22 15:09

Alex J