我需要合并2个列表。列表1只有日期,列表2也可以有时间元素:
var List1 = new[] {
new ListType{ val = new DateTime(2012, 1, 1)},
new ListType{ val = new DateTime(2012, 1, 2)}
};
List2 = new[] { new ListType{ val = new DateTime(2012, 1, 1, 5, 0, 0)} };
FinalList = new[] {
new ListType{ val = new DateTime(2012, 1, 1, 5, 0, 0)},
new ListType{ val = new DateTime(2012, 1, 2)}
};
我的方式是:
foreach (var l in List1) {
var match = List2.FirstOrDefault(q => q.val.Date == l.val);
if (match == null) continue;
l.val = match.val;
}
有没有比使用FirstOrDefault迭代List1更好的方法,然后重新分配val?它有效,所以如果Linq有一种更优雅的方式(即我错过了一些明显的东西),这更是一种好奇心。
由于
答案 0 :(得分:0)
您可以将Enumerable.Union
与自定义IEqualityComparer<ListType>
:
class ListType
{
public DateTime val { get; set; }
public class DateComparer : IEqualityComparer<ListType>
{
public bool Equals(ListType x, ListType y)
{
if (ReferenceEquals(x, y))
return true;
else if (x == null || y == null)
return false;
return x.val.Date == y.val.Date;
}
public int GetHashCode(ListType obj)
{
return obj.val.Date.GetHashCode();
}
}
}
然后......
var finalList = List2.Union(List1, new ListType.DateComparer());
答案 1 :(得分:0)
我不会摆脱循环,但为了提高效率,我会建立一个字典映射日期到第一个matchnig时间:
var dateToTime = List2
.GroupBy(d => d.Date)
.ToDictionary(g => g.Key, g => g.First());
foreach (var l in List1)
{
DateTime match;
if (dateToTime.TryGetValue(l.val, out match))
l.val = match.val;
}
LINQ用于查询项目而不是更新项目 - 如果需要更新项目,请使用非LINQ,如foreach
循环。也就是说,如果您想从第一个列表中的项目生成 new 列表,则以下内容等同于您的代码:
var newList = List1.Select(l => new ListType { val =
dateToTime.ContainsKey(l.val) ? dateToTime[l.val] : l.val }).ToList();