2015-09-18 15 views
13

Tôi đang cố gắng lọc tất cả các phần tử trong một mảng lớn hơn 10 đến một mảng mới. Tôi cố ý không sử dụng Array.prototype.filter() vì tôi muốn tìm hiểu phương pháp reduce(). Dưới đây là đoạn code tôi đã chơi vớiTại sao Array.prototype.reduce() không lấy một mảng trống làm bộ tích lũy?

var collection = [3, 5, 11, 23, 1]; 
 

 
// fileter all the elements bigger than 10 to a new array 
 

 
var output = collection.reduce(function(filteredArr, collectionElemet) { 
 
    if (collectionElemet > 10) { 
 
    return filteredArr.push(collectionElemet); 
 
    } 
 
}, []);

Tôi đã mong rằng filteredArr sẽ được khởi tạo với một mảng trống tại thời điểm thực hiện gọi lại lần đầu tiên khi nó xảy ra với rất nhiều ví dụ được cung cấp here. Nhưng khi tôi chạy mã này, tôi gặp lỗi Cannot read property 'push' of undefined, tôi đang làm phiền nó ở đâu? Cảm ơn bạn!

+0

Nếu điều kiện là đúng - bạn trả lại một số, nếu không đúng - bạn trả về một 'không xác định'. Nếu bạn chỉ muốn lọc - sử dụng 'Array.prototype.filter', mã hiện tại của bạn vì nó là xấu và gây hiểu nhầm. – zerkms

+0

@zerkms: Đó là công bằng cho mã sản xuất, không phải cho giáo dục/thử nghiệm. OP nói rõ rằng anh ta biết về 'filter', nhưng cố gắng hiểu' reduce'. – Amadan

+1

@Amadan thì đó là một nỗ lực yếu: nó có ý nghĩa để thử các chức năng hiểu biết bằng cách sử dụng usecases chúng được thiết kế cho. – zerkms

Trả lời

26

Bạn cần phải trả lại filteredArr từ chức năng ẩn danh của bạn, do đó nó được sử dụng như là previousValue cho cuộc gọi tiếp theo

var collection = [3, 5, 11, 23, 1]; 

// filter all the elements bigger than 10 to a new array 

var output = collection.reduce(function(filteredArr, collectionElement) { 
    if (collectionElement > 10) { 
    filteredArr.push(collectionElement); 
    } 
    return filteredArr; 
}, []); 
4

Array.prototype.push sẽ trở lại độ dài của mảng mới. Bạn cần trả lại bộ tích lũy. Một cách ngắn gọn để làm điều này là với Array.prototype.concat, vì phương pháp mà thực sự sẽ trở lại với mảng:

var collection = [3, 5, 11, 23, 1]; 

var output = collection.reduce(function(filteredArr, collectionElemet) { 
    if (collectionElemet > 10) { 
    return filteredArr.concat(collectionElemet); 
    } 
}, []); 

Bạn cần phải trả lại cho ác vì thế hệ tiếp theo có thể sử dụng giá trị của accumulator.

+0

Không phải của tôi downvote, nhưng * concat * trả về một mảng mới mỗi lần, đó là không hiệu quả. * push * là lựa chọn hiển nhiên cho việc thêm các phần tử mới vào một mảng hiện có. – RobG

+1

Không phải lúc nào cũng là về hiệu quả, là câu trả lời hợp lệ vì minh họa hai điều, cách tạo một giải pháp trong một dòng và @segmentationfaulter đó phải trả về filterArr. Sự nhầm lẫn của anh ta có lẽ đã nghĩ rằng filterArr.push sẽ trả về filterArr. – titusfx

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