我有SortedList<DateTime,double>
形式的大约2000个单独的时间序列。每个系列对应于给定证券的每日流动性。我想创建这些值的每日排名。如果我用for循环执行此操作,我会执行以下操作:
SortedList<DateTime,double>
。简单来说,这是每日流动性从最大到最小的排名。我可以让linq从对象中提取数据并按日期分组,但其余的超出了我的linq技能。
任何linq大师都会照顾这个?
下面概述了对象结构的简化版本。
注意:我有意创建了一个日期(2011,01,18),其中值(30)是相同的。在这种情况下,符号名称的子排名是可接受的。所以他们将排名第一名6753 JT,第二名6754 JT。 6752 JT没有该日期的值,因此不会包含它。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Ranking_Query
{
class Program
{
static void Main(string[] args)
{
// created an instance of the datasource and add 3 securities to it
Datasource ds = new Datasource() { Name = "test" };
ds.securities.Add("6752 JT", new Security() {
timeSeries = new Dictionary<string, SortedList<DateTime, double>>() {
{ "liquidity", new SortedList<DateTime, double>() {
{new DateTime(2011,01,15),30},
{new DateTime(2011,01,16),20},
{new DateTime(2011,01,17),10} } } }
});
ds.securities.Add("6753 JT", new Security()
{
timeSeries = new Dictionary<string, SortedList<DateTime, double>>() {
{ "liquidity", new SortedList<DateTime, double>() {
{new DateTime(2011,01,15),20},
{new DateTime(2011,01,16),30},
{new DateTime(2011,01,17),20},
{new DateTime(2011,01,18),30} } } }
});
ds.securities.Add("6754 JT", new Security()
{
timeSeries = new Dictionary<string, SortedList<DateTime, double>>() {
{ "liquidity", new SortedList<DateTime, double>() {
{new DateTime(2011,01,16),10},
{new DateTime(2011,01,17),30},
{new DateTime(2011,01,18),30} } } }
});
}
class Datasource
{
public string Name { get; set; }
public Dictionary<string, Security> securities = new Dictionary<string, Security>();
}
class Security
{
public string symbol { get; set; }
public Dictionary<string, SortedList<DateTime, double>> timeSeries;
}
}
}
使用这样的foreach循环输出......
foreach (var sec in rankingsBySymbol)
{
Console.WriteLine(sec.Key);
foreach (var secRank in sec)
{
Console.WriteLine(" {0} value {1} rank {2}",secRank.Date, secRank.Value, secRank.Rank);
}
}
应该如下......
6752 JT
1/15/2011 12:00:00 AM value 30 rank 1
1/16/2011 12:00:00 AM value 20 rank 2
1/17/2011 12:00:00 AM value 10 rank 3
6753 JT
1/15/2011 12:00:00 AM value 20 rank 2
1/16/2011 12:00:00 AM value 30 rank 1
1/17/2011 12:00:00 AM value 20 rank 2
1/18/2011 12:00:00 AM value 30 rank 1
6754 JT
1/16/2011 12:00:00 AM value 10 rank 3
1/17/2011 12:00:00 AM value 30 rank 1
1/18/2011 12:00:00 AM value 30 rank 2
注意:最终输出不需要包含用于计算排名的初始值,只需包括日期和排名。我已将其包括在内,因为它可以更容易理解最初的问题。
答案 0 :(得分:5)
您的数据结构并不十分清楚,但我想您需要的内容如下:
// Initial query just to get a sequence of { Symbol, Date, Value } entries.
var entries = from securityPair in ds.securities
from valuation in securityPair.Value.timeSeries["liquidity"]
select new { Symbol = securityPair.Key,
Date = valuation.Key,
valuation.Value };
// Now do the grouping, sorting and ranking
var groupedByDate = from entry in entries
group entry by entry.Date into date
select date.OrderByDescending(x => x.Value)
.ThenBy(x => x.Symbol)
// Use the overload of Select which includes the
// index within the sequence (*after* sorting)
.Select((x, index) => new {
x.Symbol,
x.Value,
x.Date,
Rank = index + 1,
});
// Now group by symbol again
var rankingsBySymbol = groupedByDate.SelectMany(day => day)
.ToLookup(tuple => tuple.Symbol,
tuple => new { tuple.Date,
tuple.Value,
tuple.Rank });
这将按符号构建一个查找,其中每个符号将包含该符号的值和该日期的排名的结果列表(按日期顺序排列)。
至少,这是计划。我根本没有测试过这个......