选择具有组最小值的组的所有元素

Select all elements of group with group's min value

提问人:user6703592 提问时间:8/16/2016 最后编辑:Gilad Greenuser6703592 更新时间:8/16/2016 访问量:336

问:

这是表格

 Tuple<dynamic, dynamic> pair = new Tuple<dynamic, dynamic>() = 
 {({ Symbol = a, Close = 1.0, Date = 2/1/2016, Vol = 0 }, { Symbol = b, Close = 1.6, Date = 2/1/2016, Vol = 0 })}   
 {({ Symbol = a, Close = 1.0, Date = 2/1/2016, Vol = 0 }, { Symbol = c, Close = 2.0, Date = 2/1/2016 , Vol = 0 })}  
 {({ Symbol = b, Close = 1.6, Date = 2/1/2016, Vol = 0 }, { Symbol = c, Close = 2.0, Date = 2/1/2016, Vol = 0 })}   
 {({ Symbol = a, Close = 1.1, Date = 2/2/2016, Vol = 0 }, { Symbol = b, Close = 1.2, Date = 2/2/2016, Vol = 0 })}
 {({ Symbol = a, Close = 1.1, Date = 2/2/2016, Vol = 0 }, { Symbol = c, Close = 2.1, Date = 2/2/2016, Vol = 0 })}   
 {({ Symbol = b, Close = 1.2, Date = 2/2/2016, Vol = 0 }, { Symbol = c, Close = 2.1, Date = 2/2/2016, Vol = 0 })}   
 {({ Symbol = a, Close = 1.4, Date = 2/3/2016, Vol = 0 }, { Symbol = b, Close = 1.4, Date = 2/3/2016, Vol = 0 })}   
 {({ Symbol = a, Close = 1.4, Date = 2/3/2016, Vol = 0 }, { Symbol = c, Close = 1.4, Date = 2/3/2016, Vol = 0 })}   
 {({ Symbol = b, Close = 1.4, Date = 2/3/2016, Vol = 0 }, { Symbol = c, Close = 1.4, Date = 2/3/2016, Vol = 0 })}   
 {({ Symbol = a, Close = 1.7, Date = 2/4/2016, Vol = 0.214285714285714 }, { Symbol = b, Close = 1.8, Date = 2/4/2016, Vol = 0.218217890235992 })}
 {({ Symbol = a, Close = 1.7, Date = 2/4/2016, Vol = 0.214285714285714 }, { Symbol = c, Close = 2.7, Date = 2/4/2016, Vol = 0.464743364189122 })}
 {({ Symbol = b, Close = 1.8, Date = 2/4/2016, Vol = 0.218217890235992 }, { Symbol = c, Close = 2.7, Date = 2/4/2016, Vol = 0.464743364189122 })}
 {({ Symbol = a, Close = 1.8, Date = 2/5/2016, Vol = 0.122450941145067 }, { Symbol = b, Close = 1.2, Date = 2/5/2016, Vol = 0.169725025739105 })}
 {({ Symbol = a, Close = 1.8, Date = 2/5/2016, Vol = 0.122450941145067 }, { Symbol = c, Close = 1.2, Date = 2/5/2016, Vol = 0.301649178342484 })}
 {({ Symbol = b, Close = 1.2, Date = 2/5/2016, Vol = 0.169725025739105 }, { Symbol = c, Close = 1.2, Date = 2/5/2016, Vol = 0.301649178342484 })}
  ......
  ......

我想选择具有最小抽象的 (min|第 1 卷 - 第 2 卷|)“2/3/2016”之后的每天(前一个日期可以是默认的) 预期形式如下:Vol

  {({ Symbol = a, Close = 1.7, Date = 2/4/2016, Vol = 0.214285714285714 }, { Symbol = b, Close = 1.8, Date = 2/4/2016, Vol = 0.218217890235992 }), Volspread = XXXX}
  {({ Symbol = b, Close = 1.2, Date = 2/5/2016, Vol = 0.169725025739105 }, { Symbol = c, Close = 1.2, Date = 2/5/2016, Vol = 0.301649178342484 }), Volspread = XXXX}
  ....... 
  .......

这里分别是最小的腹肌。Volspread

C# LINQ

评论

1赞 Jon Skeet 8/16/2016
你必须在这里使用吗?让整个事情在语义上更有意义会让你的代码更容易理解,如果不出意外的话......Tupledynamic
0赞 user6703592 8/16/2016
@Jon 飞碟 也许你可以忽略代码的第一部分,只看作一个列表(但必须存在)Tuple
0赞 Jon Skeet 8/16/2016
与其忽略它,不如提供一个最小的可重复示例,并告诉我们你想要实现的目标,这将是非常有帮助的。(目前尚不清楚您显示的代码与后面的描述有何关系。
1赞 kurakura88 8/16/2016
有什么原因为什么有 2 个预期?
0赞 user6703592 8/16/2016
@kurakura88对不起,我忘记了撇号

答:

0赞 Haukinger 8/16/2016 #1

看看有 MinByMoreLinq。这完全符合您的需求:

allPairs.GroupBy( x => x.first.Date.Date ).Select( x => x.MinBy( y => Math.Abs( y.first.Vol - y.second.Vol ) ) );

不保证语法错误;-)

1赞 Gilad Green 8/16/2016 #2

要选择每组中具有差异的项目:min

var result = pairs
    .Where(pair => pair.Item1.Date > new DateTime(2016, 2, 3))
    .Select(pair => new { Item = pair, Diff = Math.Abs(pair.Item1.Vol - pair.Item2.Vol) })
    .GroupBy(pair => pair.Item.Item1.Date)
    .SelectMany(group => group.Where(item => item.Diff.Equals(group.Min(i => i.Diff))).Select(item => item.Item))
    .ToList();

而测试数据:

List<Tuple<dynamic, dynamic>> pairs = new List<Tuple<dynamic, dynamic>>
{
 new Tuple<dynamic,dynamic>( new { Symbol = "a", Close = 1.0, Date = new DateTime(2016,2,1), Vol = 0 }, new { Symbol = "b", Close = 1.6, Date = new DateTime(2016,2,1), Vol = 0 }),
 new Tuple<dynamic,dynamic>( new { Symbol = "a", Close = 1.0, Date = new DateTime(2016,2,1), Vol = 0 }, new { Symbol = "c", Close = 2.0, Date = new DateTime(2016, 2, 1), Vol = 0 }),
 new Tuple<dynamic,dynamic>( new { Symbol = "b", Close = 1.6, Date = new DateTime(2016,2,1), Vol = 0 }, new { Symbol = "c", Close = 2.0, Date = new DateTime(2016, 2, 1), Vol = 0 }),
 new Tuple<dynamic,dynamic>( new { Symbol = "a", Close = 1.1, Date = new DateTime(2016,2,2), Vol = 0 }, new { Symbol = "b", Close = 1.2, Date = new DateTime(2016,2,2), Vol = 0 }),
 new Tuple<dynamic,dynamic>( new { Symbol = "a", Close = 1.1, Date = new DateTime(2016,2,2), Vol = 0 }, new { Symbol = "c", Close = 2.1, Date = new DateTime(2016,2,2), Vol = 0 }),
 new Tuple<dynamic,dynamic>( new { Symbol = "b", Close = 1.2, Date = new DateTime(2016,2,2), Vol = 0 }, new { Symbol = "c", Close = 2.1, Date = new DateTime(2016,2,2), Vol = 0 }),
 new Tuple<dynamic,dynamic>( new { Symbol = "a", Close = 1.4, Date = new DateTime(2016,2,3), Vol = 0 }, new { Symbol = "b", Close = 1.4, Date = new DateTime(2016,2,3), Vol = 0 }),
 new Tuple<dynamic,dynamic>( new { Symbol = "a", Close = 1.4, Date = new DateTime(2016,2,3), Vol = 0 }, new { Symbol = "c", Close = 1.4, Date = new DateTime(2016,2,3), Vol = 0 }),
 new Tuple<dynamic,dynamic>( new { Symbol = "b", Close = 1.4, Date = new DateTime(2016,2,3), Vol = 0 }, new { Symbol = "c", Close = 1.4, Date = new DateTime(2016,2,3), Vol = 0 }),
 new Tuple<dynamic,dynamic>( new { Symbol = "a", Close = 1.7, Date = new DateTime(2016,2,4), Vol = 0.214285714285714 }, new { Symbol = "b", Close = 1.8, Date = new DateTime(2016,2,4), Vol = 0.218217890235992 }),
 new Tuple<dynamic,dynamic>( new { Symbol = "a", Close = 1.7, Date = new DateTime(2016,2,4), Vol = 0.214285714285714 }, new { Symbol = "c", Close = 2.7, Date = new DateTime(2016,2,4), Vol = 0.464743364189122 }),
 new Tuple<dynamic,dynamic>( new { Symbol = "b", Close = 1.8, Date = new DateTime(2016,2,4), Vol = 0.218217890235992 }, new { Symbol = "c", Close = 2.7, Date = new DateTime(2016,2,4), Vol = 0.464743364189122 }),
 new Tuple<dynamic,dynamic>( new { Symbol = "a", Close = 1.8, Date = new DateTime(2016,2,5), Vol = 0.122450941145067 }, new { Symbol = "b", Close = 1.2, Date = new DateTime(2016,2,5), Vol = 0.169725025739105 }),
 new Tuple<dynamic,dynamic>( new { Symbol = "a", Close = 1.8, Date = new DateTime(2016,2,5), Vol = 0.122450941145067 }, new { Symbol = "c", Close = 1.2, Date = new DateTime(2016,2,5), Vol = 0.301649178342484 }),
 new Tuple<dynamic,dynamic>( new { Symbol = "b", Close = 1.2, Date = new DateTime(2016,2,5), Vol = 0.169725025739105 }, new { Symbol = "c", Close = 1.2, Date = new DateTime(2016,2,5), Vol = 0.301649178342484 }),
};

编辑前:

您可以执行以下操作:

//Remove irrelevant records and calculate diff
var result = pairs
    .Where(item => item.Item1.Date > new DateTime(2016, 2, 3))
    .Select(item => new { Item = item, Diff = Math.Abs(item.Item1.Vol - item.Item2.Vol) });

//Find min diff
var minDiff = result.Min(item => item.Diff);

//Get only records with min diff
result = result.Where(item => item.Diff.Equals(minDiff)).ToList();

另一种选择是使用 for 的 nuget 库MoreLinqMinBy

评论

0赞 user6703592 8/16/2016
对不起,我的意思是每天的最小值,你的代码只是一整天的最小值?
0赞 Gilad Green 8/16/2016
@user6703592 - 如果每个组中只想要一个项目,则将 with 和 with 替换为SelectMantSelectgroup.WhereFirstOrDefault()
0赞 user6703592 8/16/2016
@吉拉德·格林 谢谢!
0赞 user6703592 8/16/2016
确定!有一件事我不明白,为什么我们不能只替换?SelectmanySelect
0赞 Gilad Green 8/16/2016
@user6703592 - 你可以,但你不会有一个但是' - 只是看起来不像你要求的:)IEnumerable<YourType>IEnumerable<IEnumerable<YourType>