1

i'm developing in Javascript and i created folders array that contain objects:

folders = [folder1, folder2, folder3...]

Every object have some properties, one of this is docs that is an array of objects:

docs = [doc1, doc2, doc3...]

...and every object is like this:

doc1.title = 'foo'
doc1.desc = 'bar'
doc1.attr = {new: _.random(0, 1) > 0.5, read: _.random(0, 1) > 0.5}
...

I would like to create a function that extract only docs that have attr = {new: true, read: false}. I tried some underscore method such as _.each, _.sample, _.find and _.findWhere, but i can't figure out how to get from the main array a sample that contains docs with that attr properties.

Any idea?

4
  • Could you give us more code? Like what did you try with lodash .find()? Wouldn't a regular loop do the work? Commented Mar 10, 2016 at 14:13
  • 3
    remark: do not use new without quotes as a key of object. use "new" instead. Commented Mar 10, 2016 at 14:20
  • I added a working JSFiddle to my answer, tell me if it fits your needs. Commented Mar 10, 2016 at 14:54
  • Did you find a solution that fits you needs? Commented Mar 11, 2016 at 10:22

7 Answers 7

1

Using underscore first flatten the folders and then use where to get what you want:

var result = _.where( _.flatten(folders), {new: true, read: false});

Edited to work with the new structure:

var result = _.chain(folders)
    .pluck('docs')
    .flatten()
    .where({isNew: true, read: false})
    .value();

var folders = [
	{
		docs: [				
			{
				title: 'one',
				isNew: true,
				read: false
			},				{
				title: 'two',
				isNew: true,
				read: true
			}
		]
	},
	{
		docs: 
		[
			{
				title: 'three',
				isNew: false,
				read: false
			},				{
				title: 'four',
				isNew: true,
				read: false
			}
		]
	}
];

var result = _.chain(folders)
	.pluck('docs')
	.flatten()
	.where({isNew: true, read: false})
	.value();

document.getElementById('result').textContent = JSON.stringify(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.2/underscore.js"></script>

<p>
  <pre id="result"></pre>
</p>

Sign up to request clarification or add additional context in comments.

5 Comments

I didn't know _.flatten, anyway i was wrong and i edited my answer. Can you make your way working with the new structure?
Underscore or lodash are not really required here, but this should work indeed.
Apart from when you don't want to reinvent the wheel and when you want to support older browsers.
It doens't work, anyway it doesn't matter because i found a solution. Thank you anyway.
Added a code snippet and also changed the code to reflect that the doc property new is now called isNew.
0

Have you tried something like this?

var result = [];
folders.forEach(function(docs) {
    result.concat( docs.filter(function(doc) {
        return doc.attr.new && !doc.attr.read;
    });
});

Comments

0

underscore methods like .find work on arrays which are one level deep:

 var temp = [];
_.each(folders , function(docsArray){
    var result = _.where(docsArray ,  {new: true, read: false});
    if(result){
        temp.concat(result);
    }
});

Comments

0

You can achieve what you want without using underscore or lodash,just Take advantage of the built-in Array.map and Array.filter methods, here is an example :

var myResult = folders.map(function(folder){

      return myCustomDocs = folder.filter(function(doc){
            return (doc.attr.new  && !doc.attr.read);
      });
});

console.log(myResult);

Comments

0

What about a regular filter?

Working Demo

(Simply open your browser console and run the fiddle.)

doc1.filter(o => o.attr.new && !o.attr.read)

And you can also simply map() your folders array.

const _folders = folders
  .map(doc => doc.filter(o => o.attr.new && !o.attr.read))

You would get on new folders array containing arrays with only new && !read documents. Which you could flatten if needed:

const flatFolders = [].concat.apply([], _folders)

Comments

0

I found a working solution. Here is my code:

var result = [];
folders.forEach(function(item) {
    result = result.concat(_.filter(item.docs, function(doc) {
        return doc.isNew === true && doc.read === false;
    }));
});

Comments

0

If you have Node.js 5+ or use Babel, you can just do:

folders.reduce((res, arr) => res.concat(arr), [])      // flatten folders
       .filter(doc => doc.attr.new && !doc.attr.read); // remove all that don't return true

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.