Простой ответ
Чтобы объединить их в общий список без каких-либо общих данных, используя порядок их отображения, вы можете использовать метод Zip
:
var rows = reviews
.Zip(products, (r, p) => new { Review = r, Product = p })
.Zip(pages, (rp, page) => new { rp.Review, rp.Product, Page = page });
Проблема с этим решением состоит в том, что списки должны быть одинаковой длины, или ваш результат будет разделен на самый короткий список из этих трех.
Изменить:
Если вы не можете использовать .Net 4, ознакомьтесь с сообщениями в блоге Джона Скита о реализации Linq и в чистой комнате, в частности его статьи о Zip .
Если вы используете .Net 2, то попробуйте его библиотеку (возможно) или попробуйте LinqBridge
Как работать со списками различной длины
Вы можете предварительно дополнить список до желаемой длины. Я не смог найти существующий метод для этого, поэтому я бы использовал метод расширения:
public static class EnumerableExtensions
{
public static IEnumerable<T> Pad<T>(this IEnumerable<T> source,
int desiredCount, T padWith = default(T))
{
// Note: Not using source.Count() to avoid double-enumeration
int counter = 0;
var enumerator = source.GetEnumerator();
while(counter < desiredCount)
{
yield return enumerator.MoveNext()
? enumerator.Current
: padWith;
++counter;
}
}
}
Вы можете использовать его так:
var paddedReviews = reviews.Pad(desiredLength);
var paddedProducts = products.Pad(desiredLength,
new Product { Value2 = DateTime.Now }
);
Полный пример компиляции и соответствующий вывод
using System;
using System.Collections.Generic;
using System.Linq;
class Review
{
public string Value1;
}
class Product
{
public DateTime Value2;
}
class Page
{
public int Value3;
}
public static class EnumerableExtensions
{
public static IEnumerable<T> Pad<T>(this IEnumerable<T> source,
int desiredCount, T padWith = default(T))
{
int counter = 0;
var enumerator = source.GetEnumerator();
while(counter < desiredCount)
{
yield return enumerator.MoveNext()
? enumerator.Current
: padWith;
++counter;
}
}
}
class Program
{
static void Main(string[] args)
{
var reviews = new List<Review>
{
new Review { Value1 = "123" },
new Review { Value1 = "456" },
new Review { Value1 = "789" },
};
var products = new List<Product>()
{
new Product { Value2 = DateTime.Now },
new Product { Value2 = DateTime.Now.Subtract(TimeSpan.FromSeconds(5)) },
};
var pages = new List<Page>()
{
new Page { Value3 = 123 },
};
int maxCount = Math.Max(Math.Max(reviews.Count, products.Count), pages.Count);
var rows = reviews.Pad(maxCount)
.Zip(products.Pad(maxCount), (r, p) => new { Review = r, Product = p })
.Zip(pages.Pad(maxCount), (rp, page) => new { rp.Review, rp.Product, Page = page });
foreach (var row in rows)
{
Console.WriteLine("{0} - {1} - {2}"
, row.Review != null ? row.Review.Value1 : "(null)"
, row.Product != null ? row.Product.Value2.ToString() : "(null)"
, row.Page != null ? row.Page.Value3.ToString() : "(null)"
);
}
}
}
123 - 9.09.2011 22:02:22 - 123
456 - 9.09.2011 22:02:17 - (ноль)
789 - (ноль) - (ноль)
При использовании тега Join
Эта операция не логична Join
. Это потому, что вы сопоставляете по индексу, а не по каким-либо данным из каждого объекта. Каждый объект должен иметь другие общие данные (помимо их позиции в списках) для объединения в смысле Join
, который вы найдете в реляционной базе данных.