Tôi có một số IEnumerable<T>
và IEnumerable<U>
mà tôi muốn được hợp nhất thành một IEnumerable<KeyValuePair<T,U>>
nơi các chỉ mục của các phần tử được kết hợp với nhau trong KeyValuePair giống nhau. Lưu ý Tôi không sử dụng IList, vì vậy tôi không có số lượng hoặc chỉ mục cho các mục tôi đang hợp nhất. Làm thế nào tốt nhất tôi có thể thực hiện điều này? Tôi muốn một câu trả lời LINQ, nhưng bất cứ điều gì mà được công việc làm trong một thời trang thanh lịch sẽ làm việc là tốt.Làm cách nào để hợp nhất (hoặc nén) hai IEnumerables với nhau?
Trả lời
Lưu ý: Kể từ .NET 4.0, khung này bao gồm phương thức mở rộng .Zip
trên IEnumerable, được ghi lại here. Sau đây được duy trì cho hậu thế và để sử dụng trong phiên bản .NET framework sớm hơn 4.0.
tôi sử dụng các phương pháp khuyến nông:
// From http://community.bartdesmet.net/blogs/bart/archive/2008/11/03/c-4-0-feature-focus-part-3-intermezzo-linq-s-new-zip-operator.aspx
public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>(this IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> func) {
if (first == null)
throw new ArgumentNullException("first");
if (second == null)
throw new ArgumentNullException("second");
if (func == null)
throw new ArgumentNullException("func");
using (var ie1 = first.GetEnumerator())
using (var ie2 = second.GetEnumerator())
while (ie1.MoveNext() && ie2.MoveNext())
yield return func(ie1.Current, ie2.Current);
}
public static IEnumerable<KeyValuePair<T, R>> Zip<T, R>(this IEnumerable<T> first, IEnumerable<R> second) {
return first.Zip(second, (f, s) => new KeyValuePair<T, R>(f, s));
}
EDIT: sau khi bình luận tôi bắt buộc phải làm rõ và khắc phục một số điều:
- tôi ban đầu đã thực hiện Zip đầu tiên đúng nguyên văn từ Bart De Smet's blog
- Đã thêm xử lý điều tra viên (cũng là noted trên bài đăng gốc của Bart)
- Added kiểm tra tham số null (cũng đã thảo luận trong bài viết của Bart)
Nicer hơn tôi. – erikkallen
Điều này là sai vì nó giả định thứ tự bảo tồn IEnumerables. – Welbog
Sắp xếp: nó khuyến khích _caller_ đưa ra giả định. Điều này làm điều duy nhất nó có thể làm, và đôi khi giả định được thành lập tốt. –
Hãy suy nghĩ về những gì bạn đang yêu cầu một chút chặt chẽ ở đây:
Bạn muốn kết hợp hai IEnumerables trong đó "chỉ số trong những yếu tố liên kết với nhau trong KeyValuePair đều giống nhau", nhưng bạn " không có số lượng hoặcchỉ mục cho các mục tôi đang hợp nhất ".
Không đảm bảo rằng IEnumerables của bạn thậm chí được sắp xếp hoặc không được phân loại. Không có sự tương quan giữa hai đối tượng IEnumerable của bạn, vậy làm thế nào bạn có thể mong đợi để tương quan với chúng?
@welbog: Có vẻ như có một sự hiểu lầm về câu hỏi. Tôi nghĩ rằng "chỉ số" Erik có nghĩa là vị trí của phần tử trong IEnumerable (1, 2, v.v.) –
@mausch: một vị trí không được đảm bảo. Tùy thuộc vào việc thực hiện, thứ tự của hai IEnumerables có thể không phải là những gì được mong đợi. – Welbog
@welbog: nó có ý nghĩa khi gọi Zip với số đếm được không? Hoặc là nó không có ý nghĩa hoặc người gọi phải nhận thức được điều này ... Tôi không thấy bất kỳ tùy chọn nào khác. –
chưa được kiểm tra, nhưng nên làm việc:
IEnumerable<KeyValuePair<T, U>> Zip<T, U>(IEnumerable<T> t, IEnumerable<U> u) {
IEnumerator<T> et = t.GetEnumerator();
IEnumerator<U> eu = u.GetEnumerator();
for (;;) {
bool bt = et.MoveNext();
bool bu = eu.MoveNext();
if (bt != bu)
throw new ArgumentException("Different number of elements in t and u");
if (!bt)
break;
yield return new KeyValuePair<T, U>(et.Current, eu.Current);
}
}
Nhìn vào nextension:
Phương pháp Hiện nay thực hiện
IEnumerable
- ForEach Thực hiện một hành động cụ thể trên mỗi phần tử của IEnumerable.
- Nhóm các nhóm được nhóm thành nhiều kích thước giống nhau.
- Quét Tạo danh sách bằng cách áp dụng một đại biểu cho các cặp mục trong IEnumerable.
- Ít nhất Kiểm tra có ít nhất một số lượng nhất định các mục trong IEnumerable.
- AtMost Kiểm tra không có nhiều hơn một số lượng nhất định của các mục trong IEnumerable.
- Zip Tạo danh sách bằng cách kết hợp hai danh sách khác thành một danh sách.
- Chu kỳ Tạo danh sách bằng cách lặp lại danh sách khác.
MSDN có ví dụ sau Custom Sequence Operators. Và Welbog là đúng; nếu bạn không có chỉ mục trên các dữ liệu cơ bản bạn không có đảm bảo rằng các hoạt động hiện những gì bạn mong đợi.
Tôi sẽ sử dụng một cái gì đó dọc theo dòng -
IEnumerable<KeyValuePair<T,U>> Merge<T,U>(IEnumerable<T> keyCollection, IEnumerable<U> valueCollection)
{
var keys = keyCollection.GetEnumerator();
var values = valueCollection.GetEnumerator();
try
{
keys.Reset();
values.Reset();
while (keys.MoveNext() && values.MoveNext())
{
yield return new KeyValuePair<T,U>(keys.Current,values.Current);
}
}
finally
{
keys.Dispose();
values.Dispose();
}
}
này nên làm việc một cách chính xác, và dọn dẹp đúng cách sau đó.
Tôi nghĩ rằng đó là hình thức tốt để gọi nó là "zip", vì đó là một hoạt động biết trong thế giới chức năng. – Daniel
Một thực hiện từ functional-dotnet project bởi Alexey Romanov:
/// <summary>
/// Takes two sequences and returns a sequence of corresponding pairs.
/// If one sequence is short, excess elements of the longer sequence are discarded.
/// </summary>
/// <typeparam name="T1">The type of the 1.</typeparam>
/// <typeparam name="T2">The type of the 2.</typeparam>
/// <param name="sequence1">The first sequence.</param>
/// <param name="sequence2">The second sequence.</param>
/// <returns></returns>
public static IEnumerable<Tuple<T1, T2>> Zip<T1, T2>(
this IEnumerable<T1> sequence1, IEnumerable<T2> sequence2) {
using (
IEnumerator<T1> enumerator1 = sequence1.GetEnumerator())
using (
IEnumerator<T2> enumerator2 = sequence2.GetEnumerator()) {
while (enumerator1.MoveNext() && enumerator2.MoveNext()) {
yield return
Pair.New(enumerator1.Current, enumerator2.Current);
}
}
//
//zip :: [a] -> [b] -> [(a,b)]
//zip (a:as) (b:bs) = (a,b) : zip as bs
//zip _ _ = []
}
Thay Pair.New
với mới KeyValuePair<T1, T2>
(và các kiểu trả về) và bạn tốt để đi.
Là một bản cập nhật cho bất cứ ai tình cờ gặp phải câu hỏi này, Net 4.0 hỗ trợ này nguyên bản như cũ từ MS:
int[] numbers = { 1, 2, 3, 4 };
string[] words = { "one", "two", "three" };
var numbersAndWords = numbers.Zip(words, (first, second) => first + " " + second);
- 1. Cách hợp nhất hai hoặc nhiều luồng
- 2. Làm cách nào để hợp nhất hai bảng MySQL?
- 3. Làm thế nào để sử dụng Zip trên ba IEnumerables
- 4. Làm cách nào để hợp nhất hai đối tượng?
- 5. Git: Làm cách nào để hợp nhất hai nhánh chức năng và hoàn toàn khác nhau?
- 6. Làm cách nào để hợp nhất hai giải pháp Visual Studio khác nhau?
- 7. Làm cách nào để hợp nhất hai BST hiệu quả?
- 8. Làm cách nào để hợp nhất hai ngày trong JavaScript?
- 9. Làm cách nào để hợp nhất hai danh sách IQueryable
- 10. Làm cách nào để hợp nhất hai lớp trong PHP?
- 11. Làm cách nào để kết hợp tất cả các thành phần trong IEnumerable của IEnumerables?
- 12. Làm cách nào để kết hợp hai loại ràng buộc với một lôgic hoặc trong Haskell?
- 13. Có sự hợp nhất GZIP hợp nhất hai tệp GZIP mà không giải nén chúng không?
- 14. Làm thế nào để concat hoặc hợp nhất hai hoặc nhiều tập tin video trong Android?
- 15. Hợp nhất hai tệp trong linux với cột khác nhau
- 16. Làm cách nào để chuỗi hai UIGestureRecognizers lại với nhau?
- 17. Làm cách nào để hợp nhất kết quả IQueryable <T> với nhau?
- 18. Làm thế nào để "hợp nhất" hai URI trong Java?
- 19. Cách kết hợp hai hoặc nhiều tệp gzip/luồng
- 20. MongoDB: Làm thế nào để hợp nhất hai bộ sưu tập/cơ sở dữ liệu với nhau thành một?
- 21. Hợp nhất hai hình ảnh với PHP
- 22. Hợp nhất nội dung MediaWiki với nhau
- 23. Lấy một giao điểm của hai IEnumerables bằng LINQ
- 24. Làm cách nào để kết hợp hai kho lưu trữ git khác nhau thành một với hai nhánh?
- 25. làm thế nào để hợp nhất hai bảng trong postgresql
- 26. Làm cách nào để kết hợp nhiều danh sách IEnumerable với nhau
- 27. Làm cách nào để hợp nhất các cột từ hai bảng thành một đầu ra?
- 28. Hợp nhất hai kho lưu trữ khác nhau
- 29. Làm cách nào để hợp nhất hai tệp avi bằng ffmpeg?
- 30. Làm cách nào để hợp nhất hai bảng trong Access khi xóa các bản sao?
Tính đến .NET 4.0, khung đi kèm với một [Zip IEnumerable] (http://msdn.microsoft.com/en-us/library/dd267698%28v=vs.110%29.aspx) phương pháp mở rộng. –
Vẫn còn [một bài đăng blog khác] (http://blogs.msdn.com/ericlippert/archive/2009/05/07/zip-me-up.aspx) bởi Eric Lippert – n8wrl
Hài hước - Tôi vừa đọc tối qua. =) –