首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何根据对象属性的和获取List<T>项的子集

如何根据对象属性的和获取List<T>项的子集
EN

Stack Overflow用户
提问于 2017-11-09 20:48:11
回答 2查看 510关注 0票数 3

我想根据一个对象属性的值从列表中获取一个对象子集,具体来说,我想根据该属性的聚合值得到前几个对象。

我可以手动迭代列表,添加/求和属性的值,并将结果与我想要的值进行比较,但是有更好的方法吗?

例如,假设我有以下列表:

代码语言:javascript
复制
List<MyObj> MyObjList;

其中MyObj看起来是这样的:

代码语言:javascript
复制
public class MyObj
{
  public int MyValue { get; set; }
}

MyObjList具有以下对象和值,按顺序排列:

代码语言:javascript
复制
MyObjList[0].MyValue = 1;
MyObjList[1].MyValue = 3;
MyObjList[2].MyValue = 2;
MyObjList[3].MyValue = 3;
MyObjList[4].MyValue = 2;

例如,我可能希望得到前几项,其中它们的MyValue <= 5的总和,这将只返回前2个对象。

你会怎么做?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-11-09 21:17:21

您想要的是聚合和TakeWhile的结合,所以让我们编写它。

代码语言:javascript
复制
public static IEnumerable<S> AggregatingTakeWhile<S, A>(
  this IEnumerable<S> items,
  A initial,
  Func<A, S, A> accumulator,
  Func<A, S, bool> predicate) 
{
  A current = initial;
  foreach(S item in items)
  {
    current = accumulator(current, item);
    if (!predicate(current, item))
      break;
    yield return item;
  }
}

所以现在你可以说

代码语言:javascript
复制
var items = myObjList.AggregatingTakeWhile(
  0,
  (a, s) => a + s.MyValue,
  (a, s) => a <= 5);

请注意,我在这里决定在累加器更新后查询谓词;根据应用程序的不同,您可能需要稍微调整一下。

另一种解决方案是将聚合与枚举相结合:

代码语言:javascript
复制
public static IEnumerable<(A, S)> RunningAggregate<S, A>(
  this IEnumerable<S> items,
  A initial,
  Func<A, S, A> accumulator) 
{
  A current = initial;
  foreach(S item in items)
  {
    current = accumulator(current, item);
    yield return (current, item);
  }
}

现在你想要的操作是

代码语言:javascript
复制
var result = myObjList
  .RunningAggregate(0, (a, s) => a + s.MyValue)
  .TakeWhile( ((a, s)) => a <= 5)
  .Select(((a, s)) => s);

我可能弄错了元组语法;我现在手头没有。但你知道这个主意。聚合生成(sum,item)元组的序列,现在我们可以对它使用普通的序列运算符。

票数 11
EN

Stack Overflow用户

发布于 2017-11-09 21:18:29

对于传统的非Linq方法,您可以为此编写一个简单的方法:

代码语言:javascript
复制
static List<MyObj> GetItemsUntilSumEquals(List<MyObj> items, int maxSum)
{    
    if (items == null) return null;

    var result = new List<MyObj>();
    var sum = 0;

    foreach (var item in items)
    {
        if (sum + item.MyValue > maxSum) break;
        sum += item.MyValue;
        result.Add(item);
    }

    return result;
}
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47211254

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档