消除列表元素的连续重复

有没有一个“好”的方法来消除连续重复的列表元素?

例:

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

应该成为

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

– “好”我的意思是对一个新的用户和快速执行最可读和易于理解:)

一个简单而易读的解决scheme:

 List<string> results = new List<string>(); foreach (var element in array) { if(results.Count == 0 || results.Last() != element) results.Add(element); } 

你可以推出你自己的,linq风格的。

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

并用作

 array.NonConsecutive().ToArray() 

好处是它是懒惰的评估,所以你可以在任何枚举上使用它,而不必整体使用它,并链接其他linq方法(例如: array.Where(i => i != "red").NonConsecutive().Skip(1).ToArray() )。 如果你没有这个要求,你只是想与数组一起工作,像Simon Bartlett的解决scheme可能会稍微performance一些。

有关为什么必须使用两种方法的更多信息,请参见此处

您可以为此创build简单的通用方法,如下所示:

[编辑2] (非常感谢Eric Lippert)

  public static List<T> ExcludeConsecutiveDuplicates<T>(List<T> InputList) { object lastItem = null; List<T> result = new List<T>(); for (int i = 0; i < InputList.Count; i++) { if (i==0 || Object.Equals(InputList[i],lastItem) != true) { lastItem = InputList[i]; result.Add((T)lastItem); } } return result; } 

你可以在LINQ中做到这一点:

 list.Aggregate(new List<string>(), (current, next) => { if (current.Length <= 0 || current[current.Length-1] != next) current.Add(next); return current; }); 

本质上,这将创build一个初始为空的列表,贯穿整个源列表,并且只添加一个项目到目标列表,如果它不是目标列表的最后一个项目。

你可以很容易(可能更容易)没有LINQ:

 var target = new List<string>(); foreach (var item in list) { if (target.Length <= 0 || target[target.Length-1] != item) target.Add(item); } 

尝试这个:

 using System; using System.Linq; using System.Collections.Generic; namespace RemoveDuplicates { class MainClass { public static void Main (string[] args) { string[] a = new string[] { "red", "red", "red", "blue", "green", "green", "red", "red", "yellow", "white", "white", "red", "white", "white" }; for(int i = 0; i < a.Length; ++i) if (i == a.Length-1 || a[i] != a[i+1]) Console.WriteLine(a[i]); } } } 

输出:

 red blue green red yellow white red white 

parsing度:

 IList<string> stringList = new List<string>() { "red", "red", "blue", "green", "green", "red", "red", "yellow", "white", "white", "red", "white", "white" }; for (int i = 0; i < stringList.Count; i++) { // select the first element string first = stringList[i]; // select the next element if it exists if ((i + 1) == stringList.Count) break; string second = stringList[(i + 1)]; // remove the second one if they're equal if (first.Equals(second)) { stringList.RemoveAt((i + 1)); i--; } } 

纠正我的意见,如果有什么不妥请!

/ e:编辑的代码,所以它适用于“白色”,“白色”,“白色”,“白色”

function方法:

 var input = new[] {"red", "red", "blue", "green", "green", "red", "red", "yellow", "white", "white", "red", "white", "white"}; var output = input.Aggregate(new List<string>(), (runningOutput, value) => (runningOutput.LastOrDefault() == value ? runningOutput : runningOutput.Append(value))); 

预设一个扩展方法的存在类似于:

 static class Ex { public static List<T> Append<T>(this List<T> source, T value) { return new List<T>(source) { value }; } } 

根据需要提供自己的validation。

像这样,你不需要一个新的对象。

 public static void RemoveConsecutiveDuplicates<T>(this List<T> collection) { for (int i = 0; i < collection.Count - 1; i++) { if (collection[i].Equals(collection[i + 1])) { collection.RemoveAt(i); i--; } } } var collection = new [] { 2, 7, 7, 7, 2, 6, 4 }.ToList(); collection.RemoveConsecutiveDuplicates();