1

我有 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;
}

有没有比遍历 List1、使用 FirstOrDefault 然后重新分配 val 更好的方法?它有效,所以如果 Linq 有更优雅的方式(即我遗漏了一些明显的东西),这只是一种好奇心。

谢谢

4

2 回答 2

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());
于 2012-11-20T12:52:45.383 回答
0

我不会摆脱循环,但为了提高效率,我会建立一个字典,将日期映射到第一个匹配时间:

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循环。也就是说,如果您想从第一个列表中的项目生成一个列表,则以下代码等效于您的代码:

var newList = List1.Select(l => new ListType { val = 
    dateToTime.ContainsKey(l.val) ? dateToTime[l.val] : l.val }).ToList();
于 2012-11-20T12:53:13.337 回答