【问题标题】:How to append more rows to a Linq list after the condition is met满足条件后如何将更多行附加到 Linq 列表
【发布时间】:2016-08-24 09:41:49
【问题描述】:

我有一个包含项目的列表(假设有 1000 个项目)。我想从该列表中选择TimeInSecond 匹配条件的数据。

newList = oldList.Where(x => x.TimeInSecond >= 30 && x.TimeInSecond <= 90).ToList();  

// the above query returns 20 items (from 10 to 20)

但是,我需要从oldList 中追加下一个N 行数

// This is just an example of what I need, for example 10 next more items
newList = oldList.Where(x => x.TimeInSecond >= 30 && x.TimeInSecond <= 90).GetNextMoreItems(10).ToList() ; 

// the above query returns (20 + 10) 30 items (from 1 to 30)

【问题讨论】:

  • 不清楚您需要什么。你拿了那些与where 匹配的项目,然后你也只想要其他 10 个随机的?
  • @GiladGreen 是对的。
  • 大概GetNextMoreItems() 应该返回不满足条件的项目?
  • @stuartd 对!接下来的N项是否符合条件都没有关系,

标签: c# linq


【解决方案1】:

由于您在 cmets 中提到,您希望在条件为 true(已满足)的最后一个元素中添加 10 其他元素,您可以这样做。

// Get the elements where condition is satisfied.
newList = oldList
      .Where(x => x.TimeInSecond >= 30 && x.TimeInSecond <= 90)  
      .ToList() ; 

// Find the index of last element and then take 10 elements from then on.
newList = newList.Concat(oldList
                         .Skip(oldList.ToList().IndexOf(newList.Last() + 1))
                         .Take(10))
                 .ToList(); 

检查示例 Demo 以了解其工作原理。

【讨论】:

  • 这个解决方案仍然在条件满足的数据之上添加接下来的10行,我需要在后面添加这10行,从条件语句接收到的数据
  • 哦,所以订单对您很重要。让我编辑一下。
  • 这样不行,它获取集合(条件为真)并附加10个排除元素的元素)。
  • 经过验证,我注意到它不能完全正常工作。它将接下来的 10 个项目从 oldList 的顶部附加到 newList。
  • Gilad,为了支持他的回答,很好地解释了它首先获取满足where 条件的项目,然后按顺序将“oldList”中的下一个N 项目数量附加到newList。但我喜欢你的解决方案的简单性,如果它可以这样工作:-)
【解决方案2】:

您可以使用 UnionAddRange 将新的 10 项添加到现有列表中。当然,数据类型必须相同。这是 int 类型的示例:

    List<int> l1 = new List<int>() {1,2,3 };
    List<int> l2 = new List<int>() { 1,4,5,6};
    l1.AddRange(l2); // l1 now contains {1,2,3,1,4,5,6}
    // will remove duplicates  using default Equality Comparer
    var l3 = l1.Union(l2).ToList(); // contains {1,2,3,4,5,6}

用你的例子,它可能看起来像这样:

var list1 = oldList.Where(x => x.TimeInSecond >= 30 && x.TimeInSecond <= 90); 
var list2 = GetNextMoreItems(10).ToList(); 
var finalList = list1.AddRange(list2);

根据评论修改 要排除您已经选择的项目,您可以使用 Except,它与 Intersect 相反。因此,对于上面的 int 示例:

var l4 = l3.Except(l1); // contains {4,5,6}

然后,要选择一定数量的元素,附加 .Take(count)

【讨论】:

  • 我认为你错过了他没有GetNextMoreItems 方法,这实际上是问题所在。怎么做
  • Thought OP 在追加到现有列表时遇到问题。答案已更新。
【解决方案3】:

如果你想要那些匹配和N集合中的其他项目,你可以简单地做:

  1. 选项 1:where 条件或计数器

    int n = 10;
    int counter = 0;
    var values = oldList.Where(x => (x.TimeInSecond >= 30 && x.TimeInSecond <= 90) || 
                                    counter++ < n).ToList();
    
  2. 选项2:使用帮助方法避免重复条件

    Func<dynamic, bool> condition = (x) => x.TimeInSecond >= 30 && x.TimeInSecond <= 90;
    
    var result = oldList.Where(x => condition(x))
                        .Concat(oldList.Where(x => !condition(x)).Take(n));
    

如果订单很重要,并且您想购买N仅在所有匹配项之后出现的物品:

  1. 选项 1:

    int n = 10;
    var values = oldList.Select((item, index) => new { item, index })
                        .Where(x => x.item.TimeInSecond >= 30 && x.item.TimeInSecond <= 90);
    
    var lastItem = values.Max(item => item.index);
    
    var result = values.Select(item => item.item)
                       .Concat(oldList.Skip(lastItem + 1).ToList().Take(n));
    
  2. 选项 2:也许看起来更干净一些.. 不确定(并且必须在 concat 之前有 ToList()

    int n = 1;
    int lastItem = 0;
    
    var result = oldList.Where((x, i) =>
                        {
                            var outcome = x.TimeInSecond >= 30 && x.TimeInSecond <= 90;
                            if (outcome)
                                lastItem = i;
    
                            return outcome;
                        }).ToList()
                        .Concat(oldList.Skip(lastItem + 1).ToList().Take(n)); //Result: 40, 50, 100 (from data below)
    

测试:

List<dynamic> oldList = new List<dynamic>()
{
    new {TimeInSecond = 10},
    new {TimeInSecond = 40},
    new {TimeInSecond = 50},
    new {TimeInSecond = 100},
    new {TimeInSecond = 120},
};

【讨论】:

  • 谢谢吉拉德。然而,Option2 只返回 10 个项目。 Option1 给出了一些错误,IEnumerable 无法转换为列表。我还没有调试 Option1。
  • @wafers - Option2 中的哪一个?在顺序很重要的部分?我刚刚运行它(添加了测试数据),它返回了 40,50(条件匹配)、100(n = 1)
  • 嗯.. 奇怪的是我只收到了 10 件物品,但是 Option2 现在正在工作。返回正是我想要的。谢谢! (选项 1 未经我彻底测试)
  • @wafers - 我不明白你是想在 where 之后的 10 个项目(意思是在列表中,一个更大的索引值之后)还是从任何地方只取 10 个值但追加它们到列表的末尾(如果是这种情况,请参见顶部,选项 1)
  • 满足 where 条件后的 10 个数字。正是您在上面解释示例的方式。首先它从列表“40”和“50”中获取项目,然后附加下一个N 项目数,如果N=2 那么列表应该有timeInSecond“40”、“50”、“100”和“120”,并按此顺序。
猜你喜欢
  • 2013-03-27
  • 1970-01-01
  • 1970-01-01
  • 2021-08-03
  • 2017-09-15
  • 1970-01-01
  • 2018-03-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多