I need to split an object array into two variables. The first variable ( main
) should get the object with a title
. The second one ( content
) should get all other objects.
Sample data
[
{ _id: '1', title: 'Main' },
{ _id: '2', foo: 'bar' },
{ _id: '2', foo: 'bar' }
]
I did it with find()
/ filter()
commands, but is it really necessary to find twice?
const main = data.find(doc => doc.title)
const content = data.filter(doc => !doc.title)
Is it possible to extract the main object instead of finding it?
You could take a single loop approach and an object for same named arrays with a check if the property exist with in
operator .
var data = [{ _id: '1', title: 'Main' }, { _id: '2', foo: 'bar' }, { _id: '2', foo: 'bar' }], main = [], content = [], temp = { main, content }; data.forEach(doc => temp['title' in doc ? 'main' : 'content'].push(doc)); console.log(main); console.log(content);
.as-console-wrapper { max-height: 100% !important; top: 0; }
With just one object with title, you could assign the object directly and collec the other objects in an array.
var data = [{ _id: '1', title: 'Main' }, { _id: '2', foo: 'bar' }, { _id: '2', foo: 'bar' }], main, content = []; data.forEach(doc => 'title' in doc ? main = doc : content.push(doc) ); console.log(main); console.log(content);
.as-console-wrapper { max-height: 100% !important; top: 0; }
const content = data.find(doc => !doc.title)
This doesn't work, because find
returns one object only (the first found), not all the objects that don't match the condition. You'll have to use a filter for that
const content = data.filter(doc => !doc.title)
So yes, you'll have to iterate twice, one time to find the matching object, and a second time to build an array excluding the matching object.
var docs = [
{ _id: '1', title: 'Main' },
{ _id: '2', foo: 'bar' },
{ _id: '2', foo: 'bar' }
];
var doc = [],main = [];
for(_doc in docs){
if(typeof docs[_doc].title != 'undefined') {
doc.push(docs[_doc]);
continue;
}
main.push(docs[_doc]);
}
Working fiddle: https://jsfiddle.net/andreitodorut/fcLkata6/
I would do this a bit differently. The notion of partitioning a list by a predicate is worth extracting. So I might do this:
const docs = [{_id: '1', title: 'Main'},{_id: '2', foo: 'bar'},{_id: '2', foo: 'bar'}] const partition = pred => data => data.reduce( ([matches, mismatches], item) => pred(item) ? [matches.concat(item), mismatches] : [matches, mismatches.concat(item)], [[], []] ) const withTitle = partition(doc => 'title' in doc) console.log(withTitle(docs))
.as-console-wrapper { max-height: 100% !important; top: 0; }
Of course it's quite possible that withTitle
should be inlined, if it's not being reused. It's also possible that the currying I put in, my usual default, is not necessary for you, and it should read (pred, data) => data.reduce(...)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.