Tôi sử dụng hướng dẫn LINQ to Object trên một mảng được sắp xếp. Những thao tác nào tôi không nên làm để đảm bảo thứ tự của mảng không bị thay đổi?
Tôi sử dụng hướng dẫn LINQ to Object trên một mảng được sắp xếp. Những thao tác nào tôi không nên làm để đảm bảo thứ tự của mảng không bị thay đổi?
Câu trả lời:
Tôi đã kiểm tra các phương thức của System.Linq.Enumerable , loại bỏ bất kỳ kết quả nào trả về kết quả không phải là IEn. Tôi đã kiểm tra các nhận xét của từng để xác định thứ tự của kết quả sẽ khác với thứ tự của nguồn như thế nào.
Bảo quản trật tự tuyệt đối. Bạn có thể ánh xạ một phần tử nguồn theo chỉ mục đến một phần tử kết quả
Giữ gìn trật tự. Các yếu tố được lọc hoặc thêm, nhưng không được sắp xếp lại.
Phá hủy thứ tự - chúng tôi không biết thứ tự nào để mong đợi kết quả.
Xác định lại thứ tự một cách rõ ràng - sử dụng chúng để thay đổi thứ tự của kết quả
Xác định lại thứ tự theo một số quy tắc.
Chỉnh sửa: Tôi đã chuyển Phân biệt sang Bảo quản đơn hàng dựa trên việc triển khai này .
private static IEnumerable<TSource> DistinctIterator<TSource>
(IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
{
Set<TSource> set = new Set<TSource>(comparer);
foreach (TSource element in source)
if (set.Add(element)) yield return element;
}
Distinct
phương pháp) chỉ có nghĩa là nói "chưa được sắp xếp", chứ không phải "theo thứ tự không thể đoán trước". Tôi muốn nói Distinct
thuộc về loại lọc ở trên, giống như Where
.
Bạn đang thực sự nói về SQL, hay về mảng? Nói cách khác, bạn đang sử dụng LINQ to SQL hay LINQ to Object?
Các toán tử LINQ to Object không thực sự thay đổi nguồn dữ liệu gốc của họ - họ xây dựng các chuỗi được hỗ trợ hiệu quả bởi nguồn dữ liệu. Các hoạt động duy nhất thay đổi thứ tự là OrderBy / OrderByDesceinating / ThenBy / ThenByDesceinating - và thậm chí sau đó, chúng hoạt động ổn định cho các phần tử có thứ tự như nhau. Tất nhiên, nhiều thao tác sẽ lọc ra một số phần tử, nhưng các phần tử được trả về sẽ theo cùng một thứ tự.
Nếu bạn chuyển đổi sang cấu trúc dữ liệu khác, ví dụ như với ToLookup hoặc ToDipedia, tôi không tin rằng trật tự được giữ nguyên tại thời điểm đó - nhưng dù sao thì điều đó cũng hơi khác. (Tôi tin rằng thứ tự ánh xạ các giá trị cho cùng một khóa được tìm kiếm để tra cứu.)
GroupBy
theo SelectMany
sẽ đưa ra kết quả được nhóm theo khóa, nhưng không theo thứ tự khóa tăng dần ... nó sẽ cung cấp cho họ theo thứ tự các khóa ban đầu xảy ra.
list<x> {a b c d e f g}
hợp c, d, e đều có cùng khóa thì chuỗi kết quả sẽ chứa c, d, e cạnh nhau VÀ theo thứ tự c, d, e. Tôi dường như không thể tìm thấy một câu trả lời dựa trên MS phân loại.
Nếu bạn đang làm việc trên một mảng, có vẻ như bạn đang sử dụng LINQ-to-Object chứ không phải SQL; bạn có thể xác nhận? Hầu hết các hoạt động LINQ không sắp xếp lại bất cứ thứ gì (đầu ra sẽ theo cùng thứ tự với đầu vào) - vì vậy đừng áp dụng một loại khác (OrderBy [Giảm dần] / ThenBy [Giảm dần]).
[sửa: như Jon nói rõ hơn; LINQ thường tạo ra một chuỗi mới , để lại dữ liệu gốc]
Lưu ý rằng việc đẩy dữ liệu vào một Dictionary<,>
(ToDipedia) sẽ làm xáo trộn dữ liệu, vì từ điển không tôn trọng bất kỳ thứ tự sắp xếp cụ thể nào.
Nhưng những điều phổ biến nhất (Chọn, Ở đâu, Bỏ qua, Lấy) sẽ ổn.
ToDictionary()
chỉ đơn thuần là không hứa hẹn về thứ tự, nhưng trong thực tế vẫn duy trì thứ tự đầu vào (cho đến khi bạn loại bỏ thứ gì đó khỏi nó). Tôi không nói là dựa vào điều này, nhưng 'tranh giành' có vẻ không chính xác.
Tôi tìm thấy một câu trả lời tuyệt vời trong một câu hỏi tương tự tham khảo tài liệu chính thức. Để trích dẫn nó:
Đối với Enumerable
phương pháp (LINQ to Objects, áp dụng cho List<T>
), bạn có thể dựa vào thứ tự của các yếu tố được trả về bởi Select
, Where
hoặc GroupBy
. Đây không phải là trường hợp cho những thứ vốn đã không có thứ tự như ToDictionary
hoặc Distinct
.
Từ tài liệu En Enableable.groupBy :
Các
IGrouping<TKey, TElement>
đối tượng được sinh ra theo thứ tự dựa trên thứ tự của các phần tử trong nguồn tạo ra khóa đầu tiên của mỗi phần tửIGrouping<TKey, TElement>
. Các yếu tố trong một nhóm được mang lại theo thứ tự chúng xuất hiệnsource
.
Điều này không nhất thiết đúng với IQueryable
các phương thức mở rộng (các nhà cung cấp LINQ khác).
Nguồn: Các phương pháp vô số của LINQ có duy trì trật tự các yếu tố tương đối không?
Câu hỏi ở đây đặc biệt đề cập đến LINQ-to-Object.
Nếu bạn sử dụng LINQ-to-SQL thay vào đó, sẽ không có thứ tự nào trừ khi bạn áp đặt một thứ như:
mysqlresult.OrderBy(e=>e.SomeColumn)
Nếu bạn không làm điều này với LINQ-to-SQL thì thứ tự kết quả có thể khác nhau giữa các truy vấn tiếp theo, thậm chí của cùng một dữ liệu, có thể gây ra lỗi không liên tục.