Enumerator stuck in an infinite loop while removing extra items from the list

I have a script that takes an array int[], converts it to a list, and removes all subsequent occurrences of integers that have already occurred at least 2 times. The problem is that when it gets into the loop, where I check the count of each of the integers, I get stuck in the loop.

EDIT: "I left that the list should remain in the original order so that extra numbers are removed from top to bottom. Sorry if this confused those who already answered!

I thought that a changed number occursintegerOccurrencewould act like a change in the number of while loops.

Any ideas on what I'm missing here? Besides any noticeable skill.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Messaging;

public class Kata
{
    public static void Main()
    {
       int[] arr = new int[] {1, 2, 1, 4, 5, 1, 2, 2, 2};
        int occurrenceLimit = 2;
       var intList = arr.ToList();

        for (int i = 0; i < intList.Count; i++)
        {
            var occursintegerOccurrence = intList.Count(n => n == occurrenceLimit);

            do
            {
                occursintegerOccurrence = intList.Count(n => n == occurrenceLimit);
                foreach (var x in intList)
                {
                    Console.WriteLine(x);
                    intList.Remove(intList.LastIndexOf(occurrenceLimit));
                    // Tried changing the count here too
                    occursintegerOccurrence = intList.Count(n => n == occurrenceLimit);
                }
            } while (occursintegerOccurrence > occurrenceLimit);
        }
    }
}
+4
8

, , , 2, , , :

int[] arr = new int[] {1, 2, 1, 4, 5, 1, 2, 2, 2};
var ints = arr.Select((n, idx) => new {n, idx})
               .GroupBy(x => x.n)
               .SelectMany(grp => grp.Take(2))
               .OrderBy(x => x.idx)
               .Select(x => x.n)
               .ToList();

:

1, 2, 1, 4, 5, 2

Select , .

+5

 intList.Remove(intList.LastIndexOf(occurrenceLimit));

.. , occurrenceLimit (= 2), "8" ( , 0).

"8" , , , .

occurrenceLimit, , StuartLC .

int[] arr = new int[] { 1, 2, 1, 4, 5, 1, 2, 2, 2 };
int?[] arr2 = new int?[arr.Length];
arr2.ToList().ForEach(i => i = null);
int occurrenceLimit = 2;

var ints = arr.GroupBy(x => x).Select(x => x.Key).ToList();

ints.ForEach(i => {
   int ndx = 0;
   for (int occ = 0; occ < occurrenceLimit; occ++){
        ndx = arr.ToList().IndexOf(i, ndx);
        if (ndx < 0) break;
        arr2[ndx++] = i;
   }
});

List<int?> intConverted = arr2.ToList();
intConverted.RemoveAll(i => i.Equals(null));
+4

     namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] arr = new int[] { 1, 2, 1, 4, 5, 1, 2, 2, 2 };
            int occurrenceLimit = 2;
            var newList = new List<Vm>();


            var result=new List<Vm>();

            for (int i = 0; i < arr.Length; i++)
            {
                var a = new Vm {Value = arr[i], Index = i};
                result.Add(a);
            }

            foreach (var item in result.GroupBy(x => x.Value))
            {
                newList.AddRange(item.Select(x => x).Take(occurrenceLimit));
            }

            Console.WriteLine(string.Join(",",newList.OrderBy(x=>x.Index).Select(a=>a.Value)));

            Console.ReadKey();
        }
    }

    public class Vm
    {
        public int Value { get; set; }
        public int Index { get; set; }
    }
}

:

  • Vm 2 (Value Index), .

  • 2 .

  • .

+1

, , :

using System;
using System.Collections.Generic;
using System.Linq;
static class Test {
    static IEnumerable<int> KeepNoMoreThen(this IEnumerable<int> source, int limit) {
        Dictionary<int, int> counts = new Dictionary<int, int>();
        foreach(int current in source) {
            int count;
            counts.TryGetValue(current, out count);
            if(count<limit) {
                counts[current]=count+1;
                yield return current;
            }
        }
    }
    static void Main() {
        int[] arr = new int[] { 1, 2, 1, 4, 5, 1, 2, 2, 2 };
        int occurrenceLimit = 2;
        List<int> result = arr.KeepNoMoreThen(occurrenceLimit).ToList();
        result.ForEach(Console.WriteLine);
    }
}
+1
var removal = arr.GroupBy (a =>a ).Where (a =>a.Count()>2).Select(a=>a.Key).ToArray();

var output = arr.Where (a =>!removal.Contains(a)).ToList();

removal - , .

output - .

[Update - , , , )

+1

, , O (N) :

int[] arr = new int[] { 1, 2, 1, 4, 5, 1, 2, 2, 2 };
int occurrenceLimit = 2;
var counts = new Dictionary<int, int>();
var resilt = arr.Where(n =>
{
    int count;
    if (counts.TryGetValue(n, out count) && count >= occurrenceLimit) return false;
    counts[n] = ++count;
    return true;
}).ToList();
+1

, List.Remove(), Remove() , , . , . , , List.RemoveAt(), , .

, , intList.LastIndexOf(occurrenceLimit) 8, Remove() 8 , , false . :

intList.Remove(intList.LastIndexOf(occurrenceLimit));

to

intList.RemoveAt(intList.LastIndexOf(occurrenceLimit));

"" , . , , foreach.

, , , LINQ . :

1) occurenceLimit, , , . , intList[i].

2) Remove() RemoveAt().

3) foreach do while . while, , for, ( , foreach). for - originenceLimit, , occurenceLimit - , , .

    static void Main(string[] args)
    {
        int[] arr = new int[] { 1, 2, 1, 4, 5, 1, 2, 2, 2 };
        int occurrenceLimit = 2;
        var intList = arr.ToList();
        // Interestingly, this `.Count` property updates during the for loop iteration,
        // so even though we are removing items inside this `for` loop, we do not run off the
        // end of the list as Count is constantly updated.
        // Doing `var count = intList.Count`, `for (... i < count ...)` would blow up.
        for (int i = 0; i < intList.Count; i++)
        {
            // Find the number of times the item at index `i` occurs
            int occursintegerOccurrence = intList.Count(n => n == intList[i]);

            // If `occursintegerOccurrence` is greater than `occurenceLimit`
            // then remove all but the first `occurrenceLimit` number of them
            while (occursintegerOccurrence > occurrenceLimit)
            {
                // We are not enumerating the list, so we can remove items at will.
                for (var ii = 0; ii < occursintegerOccurrence - occurrenceLimit; ii++)
                {
                    var index = intList.LastIndexOf(intList[i]);
                    intList.RemoveAt(index);
                }

                occursintegerOccurrence = intList.Count(n => n == intList[i]);
            }
        }

        // Verify the results
        foreach (var item in intList)
        {
            Console.Write(item + " ");
        }

        Console.WriteLine(Environment.NewLine + "Done");
        Console.ReadLine();
    }
+1

:

var list = new List<int> { 1, 2, 1, 4, 5, 1, 2, 2, 2 };
var occurrenceLimit = 2;

list.Reverse(); // Reverse list to make sure we remove LAST elements

// We will store count of each element occurence here
var counts = new Dictionary<int, int>();

for (int i = list.Count - 1; i >= 0; i--)
{
    var elem = list[i];
    if (counts.ContainsKey(elem)) // If we already faced this element we increment the number of it occurencies
    {
        counts[elem]++;
        if (counts[elem] > occurrenceLimit) // If it occured more then 2 times we remove it from the list
            list.RemoveAt(i);
    }        
    else
        counts.Add(elem, 1); // We haven't faced this element yet so add it to the dictionary with occurence count of 1
}

list.Reverse(); // Again reverse list

A key feature of the list is that you need to go back to be able to delete items. When you cross it, as usual, it will give you an exception explaining that the list cannot be changed. But when you go back, you can delete items as you wish, as this will not affect your further operations.

0
source

All Articles