2013-03-25 40 views
10

Có chức năng JavaScript tích hợp nào để thực hiện partial sort không? Nếu không, cách tốt nhất để thực hiện nó là gì?Sắp xếp một phần trong JavaScript

Với một mảng không được phân loại của N yếu tố, tôi muốn tìm K yếu tố đó là tối thiểu đối với một số chức năng trọng với. K nhỏ hơn nhiều so với N, vì vậy sẽ không hiệu quả để sắp xếp toàn bộ mảng và lấy các phần tử K đầu tiên.

Tôi sẽ rất vui ngay cả khi có điều gì đó không chuẩn, phụ thuộc vào trình duyệt. Tôi vẫn có thể dự phòng triển khai JavaScript tùy chỉnh.

PS: Đây là thực hiện tùy chỉnh hiện tại của tôi (mà không cần dùng một hàm trọng số vào tài khoản, chỉ cần sắp xếp các yếu tố như họ đang có vì đơn giản):

function bisect(items, x, lo, hi) { 
    var mid; 
    if (typeof(lo) == 'undefined') lo = 0; 
    if (typeof(hi) == 'undefined') hi = items.length; 
    while (lo < hi) { 
    mid = Math.floor((lo + hi)/2); 
    if (x < items[mid]) hi = mid; 
    else lo = mid + 1; 
    } 
    return lo; 
} 

function insort(items, x) { 
    items.splice(bisect(items, x), 0, x); 
} 

function partialSort(items, k) { 
    var smallest = []; 
    for (var i = 0, len = items.length; i < len; ++i) { 
    var item = items[i]; 
    if (smallest.length < k || item < smallest[smallest.length - 1]) { 
     insort(smallest, item); 
     if (smallest.length > k) 
     smallest.splice(k, 1); 
    } 
    } 
    return smallest; 
} 

console.log(partialSort([5, 4, 3, 2, 1, 6, 7, 8, 1, 9], 3)); 

Thuật toán đi qua các mảng cho một lần duy nhất, theo dõi danh sách được sắp xếp của k các mục nhỏ nhất cho đến nay, bằng cách sử dụng tìm kiếm nhị phân để chèn các phần tử mới.

Vui lòng đăng các giải pháp thay thế nếu bạn nghĩ rằng chúng có thể nhanh hơn hoặc thanh lịch hơn. Thời gian rất được hoan nghênh.

+0

Tôi không rõ cách thức hoạt động của K. ví dụ: bạn đang tìm kiếm 20% hàng đầu? –

+0

Không, đó là hằng số, thường là * K * = 5, trong khi * N * có thể là vài nghìn. Ví dụ: –

+0

Vì vậy, bạn có hàng nghìn đối thủ cạnh tranh với điểm số và bạn muốn biết ai có 5 điểm số cao nhất? –

Trả lời

5

Không. Chỉ có full array sort, vì vậy bạn sẽ cần phải sử dụng triển khai của riêng bạn.

nhỏ cải thiện trên mã của bạn (tôi đã nghĩ đến việc giống hệt nhau :-) thuật toán):

function partialSort(items, k) { 
    var smallest = items.slice(0, k).sort(), 
     max = smallest[k-1]; 
    for (var i = k, len = items.length; i < len; ++i) { 
     var item = items[i]; 
     if (item < max) { 
      insort(smallest, item); 
      smallest.length = k; 
      max = smallest[k-1]; 
     } 
    } 
    return smallest; 
} 

(Thậm chí seems to be a little faster, tôi đoán do bộ nhớ đệm max biến)

2

Không có mẹ đẻ chức năng sắp xếp từng phần. Điều gần nhất với những gì bạn muốn là Array.filter.

function isSmallEnough(element, index, array) { 
    return (element <= 10); 
} 
var filtered = [12, 5, 8, 130, 44].filter(isSmallEnough); 
// filtered is [5, 8] 

Ví dụ được mượn (và hơi sửa đổi) từ liên kết ở trên.

+0

Chỉ có vấn đề là tôi không biết ngưỡng sẽ là gì trước. Tất nhiên, tôi có thể xác định giá trị * K * tối thiểu * V * trước, sau đó lọc mảng và sắp xếp nó. Không biết nếu đó là nhanh hơn so với theo dõi các yếu tố tối thiểu trong khi tìm kiếm * V * ở nơi đầu tiên. –

+0

Bạn có thể phải lặp qua từng phần tử một lần để tìm ra V là gì, và sau đó lại lọc ra từng phần tử nhỏ hơn V. O (2n) vẫn tốt hơn nhiều so với việc sắp xếp toàn bộ danh sách: O (n log n). –

+1

Nó chắc chắn nhanh hơn so với phân loại mọi thứ, nhưng tôi không chắc liệu nó nhanh hơn so với thực hiện một vượt qua mảng mà tôi nhớ các yếu tố tối thiểu * K * cho đến nay. Nó không quan trọng trong lý thuyết (như O (2n) = O (n)), nhưng có thể tạo ra sự khác biệt đáng kể trong thực tế. Tôi sẽ thử. –

Các vấn đề liên quan