简体   繁体   中英

How do I remove each N item in List until List.Count more than target value?

There is a list of short. The values of it doesn't matter like:

List<short> resultTemp = new List<short>{1,2,3,4,5,6,7,8,9...};

This code should reduse the result list count by removing each Nth item from it.

Example 1:

List<short>{1,2,3,4,5,6,7,8,9,10}.Count == 10;
var targetItemsCount = 5;

result should be {1,3,5,7,9} and result.Count should be == 5

Example 2:

List<short>{1,2,3,4,5,6,7,8,9}.Count == 9;
var targetItemsCo:nt = 3;

result should be {1,4,7} and result.Count should be == 3

But it should stop to remove it, somewhere for make result count equal targetItemsCount (42 in this code, but its value else doesn't matter). The code is:

var currentItemsCount = resultTemp.Count;

var result = new List<short>();

var targetItemsCount = 42;
var counter = 0;
var counterResettable = 0;

if (targetItemsCount < currentItemsCount)
{
    var reduceIndex = (double)currentItemsCount / targetItemsCount;

    foreach (var item in resultTemp)
    {
        if (counterResettable < reduceIndex || 
            result.Count + 1 == currentItemsCount - counter)
        {
            result.Add(item);
            counterResettable++;
        }
        else
        {
            counterResettable = 0;
        }
        counter++;
    }
}

And the resault.Count in this example equals 41, but should be == targetItemsCount == 42;

Ho do I remove each N item in List untill List.Count more then target value with C#?

If my understanding is correct:

public static void run()
{
    var inputs =
        new List<Input>{
          new Input{ 
              Value = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },`
              TargetCount = 5, ExpectedOutput= new List<int>{1,3,5,7,9} 
          },
          new Input{  
              Value = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 },
              TargetCount = 3, ExpectedOutput= new List<int>{1,4,7} 
          },
        };

    foreach (var testInput in inputs)
    {
        Console.WriteLine($"# Input = [{string.Join(", ", testInput.Value)}]");
        var result = Reduce(testInput.Value, testInput.TargetCount);
        Console.WriteLine($"# Computed Result = [{string.Join(", ", result)} ]\n");
    }
}

static List<int> Reduce(List<int> input, int targetItemsCount)
{
    while (input.Count() > targetItemsCount)
    {
        var nIndex = input.Count() / targetItemsCount;
        input = input.Where((x, i) => i % nIndex == 0).ToList();
    }
    return input;
}

class Input
{
    public List<int> ExpectedOutput;
    public List<int> Value;
    public int TargetCount;
}

Result :

Input = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Computed Result = [1, 3, 5, 7, 9 ]

Input = [1, 2, 3, 4, 5, 6, 7, 8, 9]
Computed Result = [1, 4, 7 ]

Give this a try:

var resultTemp = Enumerable.Range(1, 9).ToList();
var targetItemsCount = 3;

var roundingError = resultTemp.Count % targetItemsCount;
var reduceIndex   = (resultTemp.Count - roundingError) / targetItemsCount;

List<int> result;
if (reduceIndex <= 1)
    result = resultTemp.Take(targetItemsCount).ToList();
else
    result = resultTemp.Where((a, index) => index % reduceIndex == 0).Take(targetItemsCount).ToList();

Tried it with your given example, also gave 42 a spin with a list of 1 to 100 it will remove every 2nd item till it reaches 42 , so the last entry in the list would be 83 .

As I said, give it a try and let me know if it fits your requirement.

To guarantee you get the expected number of selected items:

double increment = Convert.ToDouble(resultTemp.Count) / targetItemsCount;

List<short> result = Enumerable.Range(0, targetItemsCount).
                                Select(x => resultTemp[(int)(x * increment)]).
                                ToList();

Note that in the following case

List<short>{1,2,3,4,5,6,7,8,9}.Count == 9;
var targetItemsCount = 6;

The result will be [1, 2, 4, 5, 7, 8] , ie rounding the index down when needed

Also, you'll need to add validation ( targetItemsCount > 0 , targetItemsCount < resultTemp.Count ...)

Link to Fiddle

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM