【问题标题】:How do I remove each N item in List until List.Count more than target value?如何删除 List 中的每个 N 项,直到 List.Count 超过目标值?
【发布时间】:2019-07-01 14:47:15
【问题描述】:

有一个简短的列表。它的值无关紧要:

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

此代码应通过从中删除每个第 N 项来重用结果列表计数。

示例 1:

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

result 应该是 {1,3,5,7,9} 并且 result.Count 应该是 == 5

示例 2:

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

result 应该是 {1,4,7} 并且 result.Count 应该是 == 3

但它应该停止删除它,在某处使结果计数等于 targetItemsCount(此代码中为 42,但其值无关紧要)。 代码是:

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

并且这个例子中的resault.Count等于41,但应该是== targetItemsCount == 42;

如何删除 List 中的每个 N 项,直到 List.Count 多于 C# 的目标值?

【问题讨论】:

  • 为什么你想这样做?当你调试通过它时,为什么它停在41而不是42?
  • 所以N是targetItemsCount?你能解释一下算法,而不是给出 3 个可能的输入和相应的输出,以免说第一个步骤吗?
  • 如果 targetItemsCount 大于源列表中的元素数怎么办?
  • @xdtTransform 我应该结合 2 个算法 1) 我应该从列表中删除元素,以防结果列表计数超过 targetItemsCount。 2)我可以通过只删除第一个或最后第 N 个项目来做到这一点,但是当我删除每个第 N 个元素时,结果会更平滑。
  • @schlonzo 它应该什么都不删除,“如果”将被跳过。

标签: c# list linq for-loop


【解决方案1】:

如果我的理解是正确的:

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

结果:

输入 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
计算结果 = [1, 3, 5, 7, 9]

输入 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
计算结果 = [1, 4, 7]

【讨论】:

    【解决方案2】:

    为保证您获得预期数量的选定项目:

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

    注意以下情况

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

    结果将是[1, 2, 4, 5, 7, 8],即在需要时向下舍入索引

    此外,您还需要添加验证(targetItemsCount &gt; 0targetItemsCount &lt; resultTemp.Count...)

    Link to Fiddle

    【讨论】:

    • 你怎么敢把.放在行尾而不是下一个新行的开头。
    • @RandRandom 所以告我
    • 就像您的解决方案一样,它解决了我的一个问题,但那是错误的. - 这只是一个不可行的问题,我永远不会投票给这样做的人。 愤怒 ;)
    • @RandRandom 用您的解决方案检查小提琴dotnetfiddle.net/hqUThq 与 74 的解决方案在 {1,2,3,4,5,6,7,8,9} 和 targetItemsCount = 5 上得到更好的传播。它的输出是 1 2 4 6 8,而你的输出是 1 2 3 4 5。这并不意味着,你的坏或不工作,它有效,但 vc 74 好一点。
    • @mr_blond - 这就是我在评论中所说的错误 - 我完全推荐他的解决方案而不是我的解决方案,接受它但不要复制他的错误位置 . 忘记你曾经看过那
    【解决方案3】:

    试试这个:

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

    用您给定的示例进行了尝试,还给了42 一个带有1100 列表的旋转,它将删除每个2nd 项目,直到它到达42,所以列表中的最后一个条目应该是83

    正如我所说,试试看,如果它符合您的要求,请告诉我。

    【讨论】:

      猜你喜欢
      • 2020-01-06
      • 2016-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-20
      相关资源
      最近更新 更多