2015-02-12 9 views
18

Trong C#, chúng tôi có Enumerable.First(predicate). Với mã này JavaScript:Bộ lọc JavaScript đầu tiên tương đương với LINQ's Enumberable.First (vị ngữ)

function process() { 
    var firstMatch = ['a', 'b', 'c'].filter(function(e) { 
    return applyConditions(e); 
    }).shift(); 

    if(!firstMatch) { 
    return; 
    } 

    // do something else 
} 

function applyConditions(element) { 
    var min = 97; 
    var max = 122; 

    var random = Math.floor(Math.random() * (max - min + 1) + min); 

    return element === String.fromCharCode(random); 
} 

khác hơn forEach, sử dụng vòng lặp, sử dụng nhiều hoặc người điều khiển hoặc ngầm gọi some(predicate), là có một cách thông minh hơn của việc tìm kiếm các firstMatch? Tốt hơn là một hàm JavaScript (một cái gì đó như filterFirst(pedicate)) mà ngắn mạch trên trận đấu đầu tiên giống như C# 's Enumerable.First() thực hiện?

FWIW, tôi đang nhắm mục tiêu thời gian chạy node.js/io.js.

Trả lời

30

Không cần phải phát minh lại bánh xe, cách chính xác để làm điều đó là sử dụng .find:

var firstMatch = ['a', 'b', 'c'].find(applyConditions); 

Nếu bạn đang sử dụng một trình duyệt không hỗ trợ .find bạn có thể polyfill it

+0

+1 Có '.find (predicate)' là chính xác những gì tôi đang tìm kiếm trong node.js. Đây vẫn là thử nghiệm và trạng thái đặc tả là bản nháp. –

+1

Nó không _really_ thực nghiệm để được công bằng :) Dự thảo đã giải quyết mà họ đang tìm ra ngữ nghĩa của những thứ khác bây giờ. –

2

Bạn có thể mô phỏng điều này trong trường hợp bạn muốn trả lại giá trị thực sự đầu tiên giá trị với reduce.

['a', 'b', 'c'].reduce(function(prev, curr) { 
    return prev || predicate(curr) && curr; 
}, false); 

chỉnh sửa: làm ngắn gọn hơn với @BenjaminGruenbaum gợi ý

+0

Dandy! 'reduce()' là khá gần với ngoại lệ mà nó gọi callback cho mỗi phần tử của mảng (trái ngược với short-circuit on first match). –

+0

@vulcanraven Tôi không nghĩ rằng nó - nó chỉ thực sự gây nhầm lẫn để làm theo - nó có thể được viết là 'return prev || predicate (curr) && curr' - cũng sẽ thất bại đối với các phần tử mảng falsey (ví dụ như tìm 0). –

+0

@BenjaminGruenbaum giảm gọi lại gọi lại cho mảng đầy đủ luôn, nó không ngắn mạch – Esailija

1

Xin lỗi nhưng đây là tầm thường như là địa ngục

function first(array, predicate) { 
    for (var i = 0; i < array.length; ++i) { 
     if (predicate(array[i])) return array[i]; 
    } 
    throw new Error("no match"); 
} 

Đó là ok để tạo trừu tượng của riêng bạn người.

+2

Nó cũng chậm để viết, nhiều dễ gây lỗi, khó đọc, và xấu xí –

+1

Không như tầm thường như bạn nghĩ. Nếu biến vị ngữ là null hoặc không xác định trừu tượng của bạn không thành công, thay vì trả về phần tử đầu tiên. Tôi không thể [1, 2] .first(), vì vậy nó không chính xác tương đương với LINQ. Và đó là lý do tại sao nó không phải là ok để tạo ra abstractions khi nó đã tồn tại. – Atomosk

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