2012-09-10 25 views
41

Hãy tưởng tượng tôi có cấu trúc mảng lồng nhau.Tương đương với underscore.js với toán tử SelectMany của LINQ là gì?

var nested = [ [1], [2], [3] ]; 

Sử dụng underscore.js, làm cách nào để tạo một mảng phẳng?

Trong C# bạn sẽ sử dụng Enumerable.SelectMany như thế này:

var flattened = nested.SelectMany(item => item); 

Lưu ý rằng lambda trong trường hợp này chọn mục lồng nhau trực tiếp, nhưng nó có thể là bất kỳ biểu hiện độc đoán.

Trong jQuery, nó có thể chỉ cần sử dụng:

var flattened = $.map(nested, function(item) { return item; }); 

Tuy nhiên phương pháp này không làm việc với chức năng gạch dưới của map.

Vậy làm cách nào để có được mảng phẳng [1, 2, 3] bằng cách sử dụng underscore.js?

+3

sử dụng _.flatten? – yngccc

+0

bạn cũng có thể viết: _.map (lồng nhau, hàm (mục) {return item [0];}) – Darragh

+0

@Darragh, sẽ hoạt động cho ví dụ cụ thể của tôi, nhưng không phải khi các mảng con chứa nhiều phần tử. –

Trả lời

35
var nested = [ [1], [2], [3] ]; 
var flattened = _.flatten(nested); 

Heres một fiddle

+0

Đẹp và dễ dàng! Tại sao tôi không thấy điều đó trong tài liệu của họ?:) –

+6

Thông báo: chuyển nông = true, nếu bạn chỉ muốn một mức làm phẳng (như SelectMany): '_.flatten (lồng nhau, đúng)' –

+2

['flatten'] (https://lodash.com/docs #flatten) xuất hiện để chỉ làm một cấp theo mặc định ngay bây giờ; họ đã thêm 'flattenDeep' và' flattenDepth'. – mpen

37

Nếu bạn có một mảng hơi phức tạp hơn, nói một đến từ JSON, bạn có thể tận dụng lợi thế của phương pháp pluck là tốt, chiết xuất tài sản cụ thể mà bạn quan tâm, tương tự để parents.SelectMany(parent => parent.Items);

// underscore version 
var allitems = _.flatten(_.pluck(parents, 'items')); 

allitems tại là mảng của tất cả các subitems từ cha mẹ, [a,b,c,d].

JSFiddle hiển thị cùng một thứ.


Hoặc, nếu bạn đang sử dụng lodash bạn có thể làm điều tương tự bằng cách sử dụng chức năng _.flatMap trong đó có sẵn từ phiên bản 4. CRED đến Noel cho trỏ nó ra trong các ý kiến.

var parents = [ 
 
    { name: 'hello', items: ['a', 'b'] }, 
 
    { name: 'world', items: ['c', 'd'] } 
 
]; 
 

 

 
// version 1 of lodash, straight up 
 
var allitems = _.flatMap(parents, 'items'); 
 
logIt('straight', allitems); 
 

 
// or by wrapping the collection first 
 
var allitems = _(parents) 
 
    .flatMap('items') 
 
    .value(); 
 
logIt('wrapped', allitems); 
 

 
// this basically does _(parents).map('items').flatten().value(); 
 

 
function logIt(wat, value) { 
 
    document.getElementById('result').innerHTML += wat + ':' + JSON.stringify(value) + '\r\n<br/>'; 
 
}
<script src="https://cdn.jsdelivr.net/lodash/4.16.6/lodash.min.js"></script> 
 
<div id="result"></div>

+1

Mặc dù không có sẵn trong gạch dưới, với lodash, bạn có thể đơn giản hóa việc sử dụng 'map' và' flatten' để chỉ sử dụng 'flatMap', như sau:' _.flatMap (cha mẹ, "các mục") '). – Noel

+0

Cảm ơn @Noel, tôi sẽ thêm nó vào câu trả lời của tôi. Không biết về điều đó khi tôi viết câu trả lời của tôi – Patrick

2

tôi không thể tìm thấy bất kỳ phương pháp trong lodash mà làm việc khá giống như SelectMany, vì vậy tôi tạo một trang bằng JS tinh khiết:

Array.prototype.selectMany = function(fn) { 
    return Array.prototype.concat(...this.map(fn)); 
}; 

Boom.

> console.log([{a:[1,2],b:'x'},{a:[3,4],b:'y'}].selectMany(o => o.a)); 
[ 1, 2, 3, 4 ] 
+0

Thật sao? Tôi đã bao gồm một mẫu làm việc trong câu trả lời của tôi .. Có gì sai với giải pháp đó? – Patrick

+0

@Patrick Thứ tự của các hoạt động. Nó trở nên khó hiểu khi có lồng nhau: 'a.selectMany (b => b.c.selectMany (d => d.e))'. Hãy thử viết lại bằng cách sử dụng giải pháp của bạn. – mpen

3

Chúng tôi cũng có thể làm cho Patrick's solution thành một mixin để nó trở thành thể kết nối:

_.mixin({ 
    selectMany: function(collection, iteratee=_.identity) { 
     return _.flatten(_.map(collection, iteratee)); 
    } 
}); 

Ví dụ:

let sample = [{a:[1,2],b:'x'},{a:[3,4],b:'y'}]; 

console.log(_.selectMany(sample, 'a')); // [ 1, 2, 3, 4 ] 
console.log(_.chain(sample).selectMany(o => o.a).filter(a => a % 2 === 0).map(a => a * 3).value()); // [ 6, 12 ] 
Các vấn đề liên quan