Những gì tôi muốn làm, phiên bản ngắn:Đếm một IOrderedEnumerable mà không tốn nhiều nó
var source = new[]{2,4,6,1,9}.OrderBy(x=>x);
int count = source.Count; // <-- get the number of elements without performing the sort
dài phiên bản:
Để xác định số phần tử trong một IEnumerable, nó là cần thiết để lặp qua tất cả các phần tử. Đây có thể là một hoạt động rất tốn kém.
Nếu IEnumerable có thể được truyền tới ICollection, khi đó số lượng có thể được xác định nhanh chóng mà không cần lặp lại. Phương thức LINQ Count() thực hiện điều này một cách tự động.
Chức năng myEnumerable.OrderBy() trả về một IOrderedEnumerable. An IOrderedEnumerable rõ ràng không thể được truyền tới ICollection, vì vậy, hãy gọi Đếm() sẽ tiêu thụ toàn bộ.
Nhưng việc sắp xếp không thay đổi số lượng thành phần và IOrderedEnumerable phải giữ nguyên tham chiếu đến nguồn của nó. Vì vậy, nếu nguồn đó là ICollection, bạn có thể xác định số lượng từ IOrderedEnumerable mà không cần tiêu thụ.
Mục tiêu của tôi là có phương thức thư viện, cần có IEnumerable với các phần tử n và sau đó lấy phần tử ở vị trí n/2;
Tôi muốn tránh lặp lại trên IEnumerable hai lần chỉ để nhận số đếm, nhưng tôi cũng muốn tránh tạo bản sao không cần thiết nếu có thể.
Đây là một bộ xương của hàm Tôi muốn tạo
public void DoSomething(IEnumerable<T> source)
{
int count; // What we do with the source depends on its length
if (source is ICollection)
{
count = source.Count(); // Great, we can use ICollection.Count
}
else if (source is IOrderedEnumerable)
{
// TODO: Find out whether this is based on an ICollection,
// TODO: then determine the count of that ICollection
}
else
{
// Iterating over the source may be expensive,
// to avoid iterating twice, make a copy of the source
source = source.ToList();
count = source.Count();
}
// do some stuff
}
LINQ được thiết kế không may trong một cách mà làm cho điều này hoàn toàn không thể. – SLaks
@SLaks: Thường thì "hoàn toàn không thể" hóa ra là có thể. Tôi nghĩ rằng bạn có thể làm điều này với cây Expression, nhưng nó vượt quá khả năng của tôi. –
Bạn có thể tạo lớp trình bao bọc của riêng mình để giữ nguồn gốc và cũng áp dụng bất kỳ thứ tự nào khi được yêu cầu không? – Rob