2015-12-21 9 views
26

Tôi có một mảng đối tượng mà tôi muốn lặp lại để tạo ra một mảng được lọc mới. Nhưng ngoài ra, tôi cần phải lọc ra một số đối tượng từ mảng mới tùy thuộc vào tham số. Tôi đang thử điều này:Bản đồ và lọc một Array cùng một lúc trong Javascript

function renderOptions(options) { 
    return options.map(function (option) { 
     if (!option.assigned) { 
      return (someNewObject); 
     } 
    }); 
} 

Đó có phải là cách tiếp cận tốt không? Có phương pháp nào tốt hơn không? Tôi mở để sử dụng bất kỳ thư viện nào như lodash.

+0

phương pháp tiếp cận "object.keys" là gì? https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Object/keys – Julo0sS

+0

Sử dụng giảm: https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Array/reduce –

Trả lời

39

Bạn nên sử dụng Array.reduce cho việc này. Thông tin

var options = [ 
 
    { name: 'One', assigned: true }, 
 
    { name: 'Two', assigned: false }, 
 
    { name: 'Three', assigned: true }, 
 
]; 
 

 
var reduced = options.reduce(function(filtered, option) { 
 
    if (option.assigned) { 
 
    var someNewValue = { name: option.name, newProperty: 'Foo' } 
 
    filtered.push(someNewValue); 
 
    } 
 
    return filtered; 
 
}, []); 
 

 
document.getElementById('output').innerHTML = JSON.stringify(reduced);
<h1>Only assigned options</h1> 
 
<pre id="output"> </pre>

thêm: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

+0

Đối với tôi, arg đầu tiên, 'lọc' là một đối tượng. do đó, 'filter.push' không được xác định cho tôi. –

+0

Tôi cũng có một vấn đề với 'lọc' là một đối tượng. Điều này là do tôi đã không đi qua "giá trị ban đầu" - mảng trống ('[]') sau hàm reduce. ví dụ: không chính xác 'var giảm = options.reduce (function (lọc, tùy chọn) { ... }); ' đúng ' var giảm = options.reduce (function (lọc, tùy chọn) { .. }, []); ' –

1

Sử dụng Array.prototy.filter tự

function renderOptions(options) { 
    return options.filter(function(option){ 
     return !option.assigned; 
    }).map(function (option) { 
     return (someNewObject); 
    }); 
} 
+0

Điều này không trả lời bất cứ điều gì. Câu hỏi đặt ra là hỏi làm cách nào để đơn giản hóa hai hàm mảng thành một. –

28

Sử dụng giảm, Luke!

function renderOptions(options) { 
    return options.reduce(function (res, option) { 
     if (!option.assigned) { 
      res.push(someNewObject); 
     } 
     return res; 
    }, []); 
} 
1

Sử dụng giảm, bạn có thể thực hiện việc này trong một hàm Array.prototype. Điều này sẽ lấy tất cả các số chẵn từ một mảng.

var arr = [1,2,3,4,5,6,7,8]; 
 

 
var brr = arr.reduce(function(c,n){ 
 
    if(n%2!=0){ 
 
     return c; 
 
    } 
 
    c.push(n); 
 
    return c; 
 

 
},[]); 
 

 
document.getElementById('mypre').innerHTML = brr.toString();
<h1>Get all even numbers</h1> 
 
<pre id="mypre"> </pre>

Bạn có thể sử dụng cùng một phương pháp và khái quát nó cho đối tượng của bạn, như thế này.

var arr = options.reduce(function(c,n){ 
    if(somecondition){return c;} 
    c.push(n); return c; 
},[]); 

arr giờ đây sẽ chứa các đối tượng được lọc.

2

Với ES6 bạn có thể làm điều đó rất ngắn:

options.filter(opt => !opt.assigned).map(opt => someNewObject)

+0

Điều này sẽ thực hiện hai vòng, tùy thuộc vào việc bộ lọc nào trả về vẫn có thể ăn bộ nhớ. – hogan

0

Tại một số điểm, không phải là nó dễ dàng hơn (hoặc chỉ là dễ dàng) để sử dụng một forEach

var options = [ 
 
    { name: 'One', assigned: true }, 
 
    { name: 'Two', assigned: false }, 
 
    { name: 'Three', assigned: true }, 
 
]; 
 

 
var reduced = [] 
 
options.forEach(function(option) { 
 
    if (option.assigned) { 
 
    var someNewValue = { name: option.name, newProperty: 'Foo' } 
 
    reduced.push(someNewValue); 
 
    } 
 
}); 
 

 
document.getElementById('output').innerHTML = JSON.stringify(reduced);
<h1>Only assigned options</h1> 
 
<pre id="output"> </pre>

Tuy nhiên, sẽ tốt hơn nếu có malter() hoặcHàmkết hợp các hàm mapfilter. Nó sẽ hoạt động giống như một bộ lọc, ngoại trừ thay vì trả về true hoặc false, nó sẽ trả về bất kỳ đối tượng nào hoặc một null/undefined.

0

tôi tối ưu hóa các câu trả lời với các điểm sau:

  1. Viết lại if (cond) { stmt; } như cond && stmt;
  2. Sử dụng ES6 Arrow Functions

tôi sẽ giới thiệu hai giải pháp, một sử dụng forEach, người kia sử dụng reduce :

Solut ion 1: Sử dụng foreach

var options = [ 
 
    { name: 'One', assigned: true }, 
 
    { name: 'Two', assigned: false }, 
 
    { name: 'Three', assigned: true }, 
 
]; 
 
var reduced = [] 
 
options.forEach(o => { 
 
    o.assigned && reduced.push({ name: o.name, newProperty: 'Foo' }); 
 
}); 
 
console.log(reduced);

Giải pháp 2: Sử dụng giảm

var options = [ 
 
    { name: 'One', assigned: true }, 
 
    { name: 'Two', assigned: false }, 
 
    { name: 'Three', assigned: true }, 
 
]; 
 
var reduced = options.reduce((a, o) => { 
 
    o.assigned && a.push({ name: o.name, newProperty: 'Foo' }); 
 
    return a; 
 
}, [ ]); 
 
console.log(reduced);

tôi để nó tùy thuộc vào bạn để quyết định giải pháp cho đi.

+0

Tại sao bạn lại sử dụng 'cond & & stmt;'? Điều này khó đọc hơn nhiều và không mang lại lợi ích gì cả. – jlh

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