我有一张桌子(日期是mm / dd / yyyy格式):
FromID ToID FromDate ToDate
S1 S2 1/1/2016 1/15/2016
S2 S3 2/1/2016 3/14/2016
S1 S2 1/5/2016 1/20/2016
S2 S3 1/25/2016 2/25/2016
S1 S2 1/21/2016 1/25/2016
我需要组合行,以便重复fromId和ToId的重叠日期。例如,对于此表,输出应为:
FromID ToID FromDate ToDate
S1 S2 1/1/2016 1/25/2016
S2 S3 1/25/2016 3/14/2016
我已尝试使用以下C#代码来完成它,但它无法正常工作。
public class MergeLists
{
static void Main(String[] args) {
List<ItemDetails> theTempList = new List<ItemDetails>();
List<ItemDetails> theOriList = new List<ItemDetails>();
DateTime minDate = new DateTime(2016, 1, 1);
DateTime maxDate = new DateTime(2016, 1, 1);
int count;
theOriList.Add(new ItemDetails("S1","S2", new DateTime(2016,1,1), new DateTime(2016,1,15)));
theOriList.Add(new ItemDetails("S2", "S3", new DateTime(2016, 2, 1), new DateTime(2016, 2, 14)));
theOriList.Add(new ItemDetails("S1", "S2", new DateTime(2016, 1, 5), new DateTime(2016, 1, 20)));
theOriList.Add(new ItemDetails("S2", "S3", new DateTime(2016, 1, 25), new DateTime(2016, 2, 25)));
theOriList.Add(new ItemDetails("S1", "S2", new DateTime(2016, 1, 21), new DateTime(2016, 1, 25)));
theOriList = theOriList.OrderBy(x => x.fromId).ThenBy(x=> x.toId).ToList();
int addnew = 0;
for (int i = 0; i < theOriList.Count; i++)
{
for (int j = i + 1; j < theOriList.Count; j++)
{
if ((theOriList[i].fromId == theOriList[j].fromId) && (theOriList[i].toId == theOriList[j].toId))
{
if ((theOriList[i].fromDate <= theOriList[j].fromDate) && (theOriList[j].fromDate <= theOriList[i].toDate))
{
if (theOriList[j].toDate > theOriList[i].toDate)
{
maxDate = theOriList[j].toDate;
minDate = theOriList[i].fromDate;
}
else if (theOriList[j].toDate < theOriList[i].toDate)
{
maxDate = theOriList[i].toDate;
minDate = theOriList[i].fromDate;
}
}
else if (theOriList[i].fromDate > theOriList[j].fromDate)
{
if (theOriList[i].toDate <= theOriList[j].toDate)
{
maxDate = theOriList[j].toDate;
minDate = theOriList[j].fromDate;
}
else if (theOriList[i].toDate > theOriList[j].toDate)
{
maxDate = theOriList[i].toDate;
minDate = theOriList[j].fromDate;
}
}
else if ((theOriList[j].fromDate > theOriList[i].toDate))
{
//Add directly
addnew = 1;
}
}
}
if (addnew != 1)
{
theTempList.Add(new ItemDetails(theOriList[i].fromId, theOriList[i].toId, minDate, maxDate));
}
else if (addnew == 1)
theTempList.Add(new ItemDetails(theOriList[i].fromId, theOriList[i].toId, theOriList[i].fromDate, theOriList[i].toDate));
}
theTempList = theTempList.OrderBy(x => x.fromId).ThenBy(x => x.toId).ToList();
foreach (ItemDetails x in theTempList)
{
Console.WriteLine("FromId: " + x.fromId + "\tToId: " + x.toId + "\tFromDate:" + x.fromDate + "\tToDate:" + x.toDate);
}
Console.ReadKey();
}
}
答案 0 :(得分:1)
GroupBy
字段需要From,To
,然后分别从Min
和Max
查找FromDate
和ToDate
个日期。
theOriList.GroupBy(x=> new {x.From, x.To })
.Select(x=> new ItemDetails(x.Key.From,x.Key.To,x.Min(m=>m.FromDate), x.Max(m=>m.ToDate)))
.ToList();
选中此Demo
答案 1 :(得分:0)
我像这样使用GroupBy和Projection
struct Thing
{
public string From { get; }
public string To { get; }
public DateTime FromDate { get; }
public DateTime ToDate { get; }
public Thing(string @from, string to, DateTime fromDate, DateTime toDate)
{
From = @from;
To = to;
FromDate = fromDate;
ToDate = toDate;
}
public override string ToString()
{
return $"{From}-{To} Dates: {FromDate.ToShortDateString()} - {ToDate.ToShortDateString()}";
}
}
[Test]
public void Grouping()
{
var items = new List<Thing>
{
new Thing("S1", "S2", new DateTime(2016, 1, 1), new DateTime(2016, 1, 1)),
new Thing("S2", "S3", new DateTime(2016, 2, 1), new DateTime(2016, 3, 14)),
new Thing("S1", "S2", new DateTime(2016, 1, 5), new DateTime(2016, 1, 20)),
new Thing("S2", "S3", new DateTime(2016, 1, 25), new DateTime(2016, 2, 25)),
new Thing("S1", "S2", new DateTime(2016, 1, 21), new DateTime(2016, 1, 25))
};
var results = items.GroupBy(i => new {i.From, i.To})
.Select(grp => new
{
grp.Key.From,
grp.Key.To,
items = grp.ToList()
})
.Select(grpd => new Thing(
grpd.From,
grpd.To,
grpd.items.Min(x => x.FromDate),
grpd.items.Max(x=> x.ToDate)));
Assert.That(results, Is.EquivalentTo(new List<Thing>
{
new Thing("S1", "S2", new DateTime(2016, 1, 1), new DateTime(2016, 1, 25)),
new Thing("S2", "S3", new DateTime(2016, 1, 25), new DateTime(2016, 3, 14))
}));
}
此处传递的NUnit测试显示了如何按两个属性进行分组,然后选择这些组的最小和最大日期。
答案 2 :(得分:0)
你可以这样做。我对linq不太好。
$ env API_KEY=XXX pm2 start app.js
答案 3 :(得分:0)
尝试linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication10
{
class Program
{
static void Main(string[] args)
{
DataTable dt = new DataTable();
dt.Columns.Add("FromID", typeof(string));
dt.Columns.Add("ToID", typeof(string));
dt.Columns.Add("FromDate", typeof(DateTime));
dt.Columns.Add("ToDate", typeof(DateTime));
dt.Rows.Add(new object[] {"S1", "S2", DateTime.Parse("1/1/2016"), DateTime.Parse("1/15/2016")});
dt.Rows.Add(new object[] {"S2", "S3", DateTime.Parse("2/1/2016"), DateTime.Parse("3/14/2016")});
dt.Rows.Add(new object[] {"S1", "S2", DateTime.Parse("1/5/2016"), DateTime.Parse("1/20/2016")});
dt.Rows.Add(new object[] {"S2", "S3", DateTime.Parse("1/25/2016"), DateTime.Parse("2/25/2016")});
dt.Rows.Add(new object[] {"S1", "S2", DateTime.Parse("1/21/2016"), DateTime.Parse("1/25/2016")});
dt = dt.AsEnumerable()
.OrderBy(x => x.Field<DateTime>("FromDate"))
.ThenBy(x => x.Field<string>("ToID"))
.ThenBy(x => x.Field<string>("ToID")).CopyToDataTable();
for (int rowNum = dt.Rows.Count - 2; rowNum >= 0; rowNum--)
{
if ((dt.Rows[rowNum]["FromID"] == dt.Rows[rowNum + 1]["FromID"]) &&
(dt.Rows[rowNum]["ToID"] == dt.Rows[rowNum + 1]["ToID"]))
{
dt.Rows[rowNum]["ToDate"] = dt.Rows[rowNum + 1]["ToDate"];
dt.Rows[rowNum + 1].Delete();
}
}
dt.AcceptChanges();
}
}
}