我正在使用linq to xml从xmlstring xmlData中提取Station数据列表。 xmldata看起来像这样:
<Observations>
<Observation>
<Station>ADELONG POST OFFICE</Station>
<DateTime>2010-09-02T00:00:00</DateTime>
<Temperature>19.212989033764689</Temperature>
</Observation>
<Observation>
<Station>ADELONG POST OFFICE</Station>
<DateTime>2010-09-01T00:00:00</DateTime>
<Temperature>28.529448969536205</Temperature>
</Observation>
<Observation>
<Station>ALBURY AIRPORT</Station>
<DateTime>2010-09-01T00:00:00</DateTime>
<Temperature>34.687027630716109</Temperature>
</Observation>
<Observation>
<Station>ALBURY AIRPORT AWS</Station>
<DateTime>2010-09-01T00:00:00</DateTime>
<Temperature>28.131385570453197</Temperature>
</Observation>
</Observations>
我正在尝试查询此xmlstring以仅提取最近日期时间的工作站名称。我也想找回最近的温度。
我已定义了一个电台班级:
public class Station
{
public string Name { get; set; }
public DateTime MostRecentDate { get; set; }
public decimal LastTemperature { get; set; }
}
如何列出每个电台的最新温度+日期时间+名称?
我在c#console应用程序中运行它(完整代码):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
namespace weatherxml
{
class Program
{
static void Main(string[] args)
{
string xmlData = @"<Observations><Observation><Station>ADELONG POST OFFICE</Station><DateTime>2010-09-02T00:00:00</DateTime><Temperature>19.212989033764689</Temperature></Observation><Observation><Station>ADELONG POST OFFICE</Station><DateTime>2010-09-01T00:00:00</DateTime><Temperature>28.529448969536205</Temperature></Observation><Observation><Station>ALBURY AIRPORT</Station><DateTime>2010-09-01T00:00:00</DateTime><Temperature>34.687027630716109</Temperature></Observation><Observation><Station>ALBURY AIRPORT AWS</Station><DateTime>2010-09-01T00:00:00</DateTime><Temperature>28.131385570453197</Temperature></Observation></Observations>";
XDocument weatherData = XDocument.Parse(xmlData);
var stations = from item in weatherData.Descendants("Observation")
select new Station
{
Name = item.Element("Station").Value,
MostRecentDate = DateTime.Parse(item.Element("DateTime").Value),
LastTemperature = Decimal.Parse(item.Element("Temperature").Value)
};
var st = stations;
foreach (var s in st)
{
Console.WriteLine(s.Name);
}
Console.ReadLine();
}
}
public class Station
{
public string Name { get; set; }
public DateTime MostRecentDate { get; set; }
public decimal LastTemperature { get; set; }
}
}
答案 0 :(得分:0)
这里有Link到另一个类似于你的StackOverflow问题
转换为您的要求您应该拥有与此类似的代码:
var op = from station in stations
group station by station.Name into grp
let recentTimestamp = grp.OrderByDescending(t => t.MostRecentDate).FirstOrDefault()
select recentTimestamp;
您也可以尝试取消我提供的第二个LINQ查询,并将它们与您自己的相结合,如果您只想要选择最近的项目。
答案 1 :(得分:0)
使用Groupby子句
var st =来自车站的s 将s.Name分组到结果中 选择新的{Station = result.Key,MostRecent = result.Max(item =&gt; item.MostRecentDate)};
foreach (var s in st)
{
Console.WriteLine(s.MostRecent);
Console.WriteLine(s.Station);
}
答案 2 :(得分:0)
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
namespace weatherxml
{
class Program
{
static void Main(string[] args)
{
string xmlData = @"<Observations><Observation><Station>ADELONG POST OFFICE</Station><DateTime>2010-09-02T00:00:00</DateTime><Temperature>19.212989033764689</Temperature></Observation><Observation><Station>ADELONG POST OFFICE</Station><DateTime>2010-09-01T00:00:00</DateTime><Temperature>28.529448969536205</Temperature></Observation><Observation><Station>ALBURY AIRPORT</Station><DateTime>2010-09-01T00:00:00</DateTime><Temperature>34.687027630716109</Temperature></Observation><Observation><Station>ALBURY AIRPORT AWS</Station><DateTime>2010-09-01T00:00:00</DateTime><Temperature>28.131385570453197</Temperature></Observation></Observations>";
var stl = new List<Station>();
using (DataSet ds = new DataSet())
{
ds.ReadXml(new StringReader(xmlData));
//i want proper types, not strings
DataColumn dc = ds.Tables[0].Columns.Add("dt", typeof(DateTime));
dc.Expression = "DateTime";
dc = ds.Tables[0].Columns.Add("temp", typeof(Decimal));
dc.Expression = "Temperature";
//group by
var result = ds.Tables[0].AsEnumerable().GroupBy(a => a.Field<string>("Station")).Select(g => g.OrderByDescending(a => a.Field<DateTime>("dt")));
//create result
foreach(var i in result)
{
var fi = i.First();
stl.Add(new Station() { Name = fi.Field<string>("Station"), LastTemperature = fi.Field<decimal>("temp"), MostRecentDate = fi.Field<DateTime>("dt") });
}
//here the stationList (stl) has info for all stations
}
Console.ReadLine();
}
}
public class Station
{
public string Name { get; set; }
public DateTime MostRecentDate { get; set; }
public decimal LastTemperature { get; set; }
}
}
答案 3 :(得分:0)
尝试按站名对数据进行分组,然后选择具有每组最大日期的观察。这个linq查询应该有效:
var stations = from item in weatherData.Descendants("Observation")
group item by (string) item.Element("Station")
into g
let date = g.Max(o => DateTime.Parse((string)o.Element("DateTime")))
select new
{
Name = g.Key,
MostRecentDate = date,
LastTemperature = Decimal.Parse((string)g.FirstOrDefault(o => date == DateTime.Parse((string)o.Element("DateTime"))).Element("Temperature"))
};
但这种方式更具可读性:
var query = from item in weatherData.Descendants("Observation")
group item by (string) item.Element("Station")
into g
select g;
var stations = new List<Station>();
foreach (var q in query)
{
//maximum date in current group
var maxDate = q.Max(o => DateTime.Parse((string) o.Element("DateTime")));
//1st observation having date equal maximum date
var latestObservation = q.FirstOrDefault(o => DateTime.Parse((string) o.Element("DateTime")) == maxDate);
//create new Station using data from latest observation
var newStation = new Station();
newStation.Name = q.Key;
newStation.MostRecentDate = maxDate;
newStation.LastTemperature = Decimal.Parse((string)latestObservation.Element("Temperature"));
//add newly created Station to result list
stations.Add(newStation);
}