Tôi có danh sách khoảng 10.000 nhân viên trong một List<T>
và tôi có một số ListBox
chứa một tập con của những nhân viên đó, tùy thuộc vào cụm từ tìm kiếm trong hộp văn bản.Kết hợp chuỗi tốc độ cao trong C#
Nói một đối tượng Staff
có các tính chất tiếp xúc công khai sau đây:
string FirstName
string LastName
string MiddleName
int StaffID
int CostCentre
tôi có thể viết một hàm như thế này:
bool staffMatchesSearch(Staff stf)
{
if (tbSrch.Text.Trim() == string.Empty)
return true; // No search = match always.
string s = tbSrch.Text.Trim().ToLower();
// Do the checks in the order most likely to return soonest:
if (stf.LastName.ToLower().Contains(s))
return true;
if (stf.FirstName.ToLower().Contains(s))
return true;
if (stf.MiddleName.ToLower().Contains(s))
return true;
if (stf.CostCentre.ToString().Contains(s))
return true; // Yes, we want partial matches on CostCentre
if (stf.StaffID.ToString().Contains(s))
return true; // And also on StaffID
return false;
}
và sau đó làm điều gì đó như:
tbSrch_TextChanged(object sender, EventArgs e)
{
lbStaff.BeginUpdate();
lbStaff.Items.Clear();
foreach (Staff stf in staff)
if (staffMatchesSearch(stf))
lbStaff.Items.Add(stf);
lbStaff.EndUpdate();
}
Bộ lọc được đánh giá lại mỗi khi người dùng thay đổi nội dung của ô tbSrch
.
Làm việc này và không phải là awfully chậm, nhưng tôi đã tự hỏi liệu mình có thể làm nhanh hơn không?
Tôi đã cố gắng viết lại toàn bộ nội dung là đa luồng, tuy nhiên chỉ có 10.000 nhân viên ở trên cao dường như lấy đi phần lớn lợi ích. Ngoài ra, có một loạt các lỗi khác như tìm kiếm "John", trước tiên người dùng nhấn "J" để cuộn lên các chuỗi, nhưng khi người dùng nhấn "o", một bộ khác sẽ được đặt lên trước khi lô đầu tiên có một cơ hội để trả lại kết quả của họ. Rất nhiều thời gian, kết quả được trả lại trong một trật tự lộn xộn và tất cả những điều khó chịu xảy ra.
Tôi có thể nghĩ đến một vài chỉnh sửa sẽ làm cho kịch bản tốt nhất tốt hơn đáng kể, nhưng chúng cũng sẽ khiến kịch bản xấu nhất tồi tệ hơn nhiều.
Bạn có ý tưởng nào về cách cải thiện điều này không?
gợi ý tuyệt vời tôi đã thực hiện đến nay, và kết quả của họ:
- Thêm một sự chậm trễ trên các sự kiện
ValueChanged
do đó nếu người dùng gõ một tên 5 ký tự một cách nhanh chóng trên bàn phím, nó chỉ thực hiện 1 tìm kiếm ở cuối thay vì 5 trong chuỗi. - Đánh giá trước
ToLower()
và lưu trữ trong lớpStaff
(dưới dạng thuộc tính[NonSerialized]
để nó không chiếm nhiều không gian hơn trong tệp lưu). - Thêm một tài sản
get
trongStaff
trả về tất cả các tiêu chí tìm kiếm dưới dạng chuỗi đơn, dài, thấp hơn, được nối. Sau đó chạy một đơnContains()
trên đó. (String này được lưu trữ trong đối tượngStaff
vì vậy nó chỉ được xây dựng một lần.)
Cho đến nay, những điều này đã làm giảm thời gian tìm kiếm từ khắp nơi trên 140ms xuống còn khoảng 60ms (mặc dù những con số này rất chủ quan tùy thuộc vào việc tìm kiếm thực tế thực hiện và số lượng kết quả được trả lại).
bạn có thực sự muốn cho 'toString' những' int's? Có vẻ như bạn muốn có một phương thức chuỗi phù hợp và phù hợp với phương pháp int ... Ý tôi là, nếu tôi ở trung tâm 13, tôi không nên xuất hiện vì ai đó tìm kiếm trung tâm 1 hoặc trung tâm 3 ... – corsiKa
Hãy thử triển khai một phương pháp trong chuỗi các thuật toán tìm kiếm chuỗi Boyer-Moore? Tiền xử lý hoặc thuật ngữ tìm kiếm, hoặc các đối tượng Staff và tái sử dụng kết quả có thể tiết kiệm rất nhiều thời gian. – millimoose
Bạn có thực sự muốn tìm kiếm tất cả các kết quả phù hợp cho từng thuộc tính của nhân viên mỗi lần không? Là người dùng, tôi chỉ muốn tìm kiếm trên một hoặc hai trường đã biết tại một thời điểm. – ChandlerPelhams