我有三个相同长度的List<string>
个包含不同类型的数据。例如:
List<string> dates = new List<string>() { "20120301", "20120401", "20120501", "20120601", "20120701"};
List<string> times = new List<string>() { "0500", "0800", "0100", "1800", "2100" };
List<string> quantities = new List<string>() { "1", "2", "1", "3", "1" };
实际数据可以是任何数据,但列表的长度始终相同。我想将它们合并为一个List<DTQ>
。
public struct DTQ
{
DateTime dt;
double q;
public DTQ(DateTime dt, double q) { this.dt = dt; this.q = q; }
}
有没有办法用lambda函数做到这一点?到目前为止,我已经设法创建了一个lambda函数,该函数描述了如果数据是strings
而不是List<string>
s,我将如何映射数据:
Func<string, string, string, DTQ> mergeFields = (d, t, q)
=> new DTQ(DateTime.ParseExact(string.Format("{0}{1}", d, t), "yyyyMMddhhmm", CultureInfo.InvariantCulture), double.Parse(q));
但是,我不知道我可以从哪里去。我们的想法是将此函数应用于列表的每个索引。
答案 0 :(得分:3)
看起来像Zip
的作业,除了你有3个列表而不是2个。
使用您当前的mergeFields
定义,您可以执行以下操作:
var dateAndTimes = dates.Zip(times, (d, t) => new { Date = d, Time = t });
var all = dateAndTimes.Zip(quantities, (dt, q) => new { dt.Date, dt.Time, Quantity = q });
var result = all.Select(x => mergeFields(x.Date, x.Time, x.Quantity)).ToList();
如果你想要一个更通用的解决方案,你也可以创建一个需要3个集合的Zip
重载:
public static IEnumerable<TResult> Zip<TFirst, TSecond, TThird, TResult>(
this IEnumerable<TFirst> first,
IEnumerable<TSecond> second,
IEnumerable<TThird> third,
Func<TFirst, TSecond, TThird, TResult> resultSelector)
{
return first.Zip(second, (f, s) => new { f, s })
.Zip(third, (fs, t) => resultSelector(fs.f, fs.s, t));
}
(或者,您可以使用Romoku的实现,这可能会快一点)
然后像这样使用它:
var result = dates.Zip(times, quantities, mergeFields).ToList();
答案 1 :(得分:2)
你可以做双拉链,但效率很低。这是一个拉链三个枚举的扩展方法。
public static class EnumerableExtensions
{
public static IEnumerable<TResult> Zip<TFirst, TSecond, TThird, TResult>(
this IEnumerable<TFirst> first,
IEnumerable<TSecond> second,
IEnumerable<TThird> third,
Func<TFirst, TSecond, TThird, TResult> resultSelector )
{
if( first == null )
throw new ArgumentNullException( "first cannot be null" );
if( second == null )
throw new ArgumentNullException( "second cannot be null" );
if( third == null )
throw new ArgumentNullException( "third cannot be null" );
if(resultSelector == null)
throw new ArgumentNullException( "resultSelector cannot be null" );
using ( var iterator1 = first.GetEnumerator() )
using ( var iterator2 = second.GetEnumerator() )
using ( var iterator3 = third.GetEnumerator() )
{
while ( iterator1.MoveNext() && iterator2.MoveNext() && iterator3.MoveNext() )
{
yield return resultSelector(
iterator1.Current,
iterator2.Current,
iterator3.Current );
}
}
}
}
用法:
var result = dates.Zip(times, quantities, mergeFields);