Eliminate consecutive duplicates of list elements

前端 未结 11 1481
南笙
南笙 2020-12-03 02:31

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

Example:

[\"red\"; \"red\"; \"blue\"; \"green         


        
相关标签:
11条回答
  • 2020-12-03 02:54

    You can create simple generic method for this purpose, like below:

    [EDIT 2] (great thanks to 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;
        }
    
    0 讨论(0)
  • 2020-12-03 02:54

    Here is my suggestion. It is similar to @AlexJ's answer, with the addition of an IEqualityComparer parameter that allows to customize the equality check. I also removed the otherwise correct separation of argument-check and implementation, because this solution is not intended to be of Library-grade quality. As for the name I adopted the ExcludeConsecutiveDuplicates from @AntonSemenov's answer.

    public static IEnumerable<TSource> ExcludeConsecutiveDuplicates<TSource>(
        this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer = null)
    {
        if (source == null) throw new ArgumentNullException(nameof(source));
        comparer = comparer ?? EqualityComparer<TSource>.Default;
        bool isFirst = true;
        TSource last = default;
        foreach (var item in source)
        {
            if (isFirst || !comparer.Equals(item, last)) yield return item;
            isFirst = false;
            last = item;
        }
    }
    

    Usage example:

    var source = new string[]
    {
        "Red", "red", "blue", "green", "green", "red", "red", "yellow",
        "WHITE", "white", "red", "white", "white"
    };
    var result = source.ExcludeConsecutiveDuplicates(StringComparer.OrdinalIgnoreCase);
    Console.WriteLine($"Result: {String.Join(", ", result)}");
    

    Output:

    Result: Red, blue, green, red, yellow, WHITE, red, white
    

    The advantage of this solution compared to the accepted answer is that it doesn't require a source of type IList<T> to be efficient.

    0 讨论(0)
  • 2020-12-03 02:56

    Resolution:

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

    correct me in the comments if something is wrong please!

    /e: Edited code so it works on "white","white","white","white"

    0 讨论(0)
  • 2020-12-03 02:57

    Functional approach:

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

    Presupposes the existence of an extension method similar to:

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

    Supply your own validation as you feel is necessary.

    0 讨论(0)
  • 2020-12-03 03:01

    Try this:

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

    Output:

    red
    blue
    green
    red
    yellow
    white
    red
    white
    
    0 讨论(0)
  • 2020-12-03 03:01

    Taking @Simon Bartlett's clean approach and improving upon it, you could also perform this generically.

    public static IEnumerable<T> UniqueInOrder<T>(IEnumerable<T> iterable)
    {
        var returnList = new List<T>();
    
        foreach (var item in iterable)
        {
            if (returnList.Count == 0 || !returnList.Last().Equals(item))
                returnList.Add(item);
        }
    
        return returnList;
    }
    
    0 讨论(0)
提交回复
热议问题