_.each vs _.map what is the difference? - coffeescript

I tried to print all the animals in my list. and I tried to use _.each and it work fine. but when I use _.map, they have the same result.
code:
animals = [ "dog","cat","pig" ]
using _.map:
_.map animals, (animal)->
console.log " " + animal
//result: dog cat pig
using _.each:
_.each animals, (animal)->
console.log " " + animal
//result: dog cat pig
Question:
what is the difference between those two?
what is the main/super function of these two?
I am new in JavaScript and I tried to read the Underscore documentation but i did not understand some of the terminologies.

_.each is just a for-loop that executes the given function for each element.
_.map collects the return value of the given function for each element and returns a list of all the return values in order.
If you discard the result of _.map (as in your example) it does the same as _.each but wastes some memory.
Therefore, functionally _.map is a superset of _.each, but implementation-wise it is unwise to use it if you don't actually need the results.

_.each doesn't return a value while
_.map returns a value
Example:
var animals = [ "dog","cat","pig" ]
var newAnimalEach = _.each(animals,(animal)=>{ return animal+'s'})
console.log(newAnimalEach) // returns [ "dog","cat","pig" ]
var newAnimalMap = _.map(animals,(animal)=>{ return animal+'s'})
console.log(newAnimalMap) // returns [ "dogs","cats","pigs" ]

Related

mongodb mapreduce can save emit into collection?

I have a function map created, is this
var m = function() {
hashtags = {}
for(var i in this.entities.hashtags) {
hashtags[this.entities.hashtags[i].text] = 1
};
var valor = {numtweets: 1 ,
dic_hastag: hashtags};
print(" value: " + tojson(valor));
emit(this.place.country_code, valor)
};
I start from a collection called tweets, and the output of my map function should have a variable numtweets: 1 and a variable hastags with the entire list of tweet hastats with a 1.
example
Nuwtweets: 1, hastags: "hast1": 1, "hast2": 2, "hast3": 1
1.- I can have the result saved in a collection, to prove that it works well instead of print
2.- If not if I have to do mapreduce, what should be the function reduces, why not do anything, and so when executing this, the output of the map function
Db.runCommand ({
MapReduce: "tweets",
Map: m,
Reduce: r,
Query: {"place.country_code": "AD"},
Out: {replace: "resultat5fi"}
});
Any suggestions, help, anything will be welcome.
I suggest you to see this.
This the way to debug map functions easily with mongodb.
first, create your map function as you did
Then define an emit function that will print (or insert into a collection)
Example of emit function that insert into a toto collection.
var emit = function(key, value) {
db.toto.insert({key: key, value: value});
}
Invoke a find function and apply your map function on each record
Example :
var myCursor = db.tweets.find( {} );
while (myCursor.hasNext()) {
var doc = myCursor.next();
map.apply(doc);
print();
}
Then look at yout toto collection
This way :
db.toto.find()

Cypher Http request with match parameters

I'd like to execute an http cypher query with parameters like :
{"statements":
[
{"statement":"MATCH path=(p:Person {props})-[*..100]->() RETURN [n in nodes(path)]",
"parameters":{"props":{"name":"Lucille"}}
}
]
}
However i get the following error Parameter maps cannot be used in MATCH patterns (use a literal map instead, eg. \"{id: {param}.id}\").
I have no idea how to use a literal map here.
Thanks for your help !
You can either have:
{
"statements": [{
"statement": "MATCH path=(p:Person { name: {name} })-[*..100]->() ...",
"parameters": { "name": "Lucille" }
}]
}
or MATCH path=(p:Person { name: props.{name} }) ... while keeping you initial parameters
The reason is given in this comment:
"Unlike properties in CREATE, MATCH requires the map to be a literal. This is because the property names must be known in advance, when the query is compiled, in order to efficiently plan its execution."
I think your query would become:
MATCH path=(p:Person {id: {props}.id })-[*..100]->()
RETURN [n in nodes(path)]

Printing out array in constructor coffeescript

This should print out everything in collection
but it only prints out two elements.
Why won't it print out the entire list?
Is it some kind of race case?
http://jsfiddle.net/Czenu/1/
class window.Restful
constructor:->
_.each #collection, (action,kind)=>
$('.actions').append "<div>#{action} #{kind}</div>"
class Material extends Restful
namespace: 'admin/api'
table_name: 'materials'
constructor:(#$rootScope,#$http)->
super
collection:
get: 'downloaded'
get: 'incomplete'
get: 'submitted'
get: 'marked'
get: 'reviewed'
get: 'corrected'
get: 'completed'
post: 'sort'
post: 'sort_recieve'
new Material()
Your collection object consists of elements with just two different keys: "get" and "post". Since each key can only map to one value, your object is reduced to:
collection:
get: 'downloaded'
...
get: 'corrected'
get: 'completed'
post: 'sort'
post: 'sort_recieve'
The solution is to make more senseful objects, for instance an array of custom objects (created using a shortcut function with a senseful name, as in the example below.).
class window.Restful
constructor: ->
_.each #collection, (obj) =>
{action,kind} = obj
$('.actions').append "<div>#{action} #{kind}</div>"
class Material extends Restful
get = (action) -> {action, kind:'get'}
post = (action) -> {action, kind:'post'}
...
collection: [
get 'downloaded'
get 'incomplete'
get 'submitted'
get 'marked'
get 'reviewed'
get 'corrected'
get 'completed'
post 'sort'
post 'sort_recieve'
]
The full result is shown at http://jsfiddle.net/Czenu/2/.

Generating Javascript from coffeescript equivalent to manual javascript in _.each underscore

I have a code in Javascript as :
_.each(this.collection.models, function (student) {
$(this.el).append(new StudCloneItemView({ model: student }).el);
}, this);
While I am writing This in coffescript as
_.each this.collection.models , (student) =>
$(#el).append new Item ({ model:student }).el
which generates
_.each(this.collection.models, function(student) {
return $(_this.el).append(new Item({
model: student
}.el));
});
Which isn't desirable as per my requirement . The last segment of "this" element has been missing into the generated javascript . Its very important.
How would I generate The javascript as mentioned on top using the coffeescript I mentioned for _.each ????
Is there anyway to do that ?? Or am I missing any syntax ?
Your JavaScript:
_.each(this.collection.models, function (student) {
$(this.el).append(new StudCloneItemView({ model: student }).el);
}, this);
and what your => CoffeeScript produces:
var _this = this; // This is somewhere above your _.each in the generated JS
_.each(this.collection.models, function(student) {
return $(_this.el).append(new Item({
model: student
}.el));
});
are functionally equivalent. You don't need the context argument to _.each since the => generates an alias for this (called _this) that is used inside the callback.
As an aside, Backbone collections have various Underscore methods mixed in so you don't have to say _.each(#collection.models, ...), you can use each directly on the collection:
#collection.each (student) =>
#$el.append(new StudCloneItemView(model: student).el)
I've also switched to the pre-built $el that your view already has, there's no need to build a new jQuery object on each iteration.
like this:
_.each #collection.models, ((student) ->
$(#el).append new StudCloneItemView(model: student).el
), this

How to access this._id in map function in MongoDB MapReduce?

I'm doing a MapReduce in Mongo to generate a reverse index of tokens for some documents. I am having trouble accessing document's _id in the map function.
Example document:
{
"_id" : ObjectId("4ea42a2c6fe22bf01f000d2d"),
"attributes" : {
"name" : "JCDR 50W38C",
"upi-tokens" : [
"50w38c",
"jcdr"
]
},
"sku" : "143669259486830515"
}
(The field ttributes['upi-tokens'] is a list of text tokens I want to create reverse index for.)
Map function (source of the problem):
m = function () {
this.attributes['upi-tokens'].forEach(
function (token) { emit(token, {ids: [ this._id ]} ); }
); }
Reduce function:
r = function (key, values) {
var results = new Array;
for (v in values) {
results = results.concat(v.ids);
}
return {ids:results};
}
MapReduce call:
db.offers.mapReduce(m, r, { out: "outcollection" } )
PROBLEM Resulting collection has null values everywhere where I'd expect an id instead of actual ObjectID strings.
Possible reason:
I was expecting the following 2 functions to be equivalent, but they aren't.
m1 = function (d) { print(d['_id']); }
m2 = function () { print(this['_id']); }
Now I run:
db.offers.find().forEach(m1)
db.offers.find().forEach(m2)
The difference is that m2 prints undefined for each document while m1 prints the ids as desired. I have no clue why.
Questions:
How do I get the _id of the current object in the map function for use in MapReduce? this._id or this['_id'] doesn't work.
Why exactly aren't m1 and m2 equivalent?
Got it to work... I made quite simple JS mistakes:
inner forEach() in the map function seems to overwrite 'this' object; this is no longer the main document (which has an _id) but the iterated object inside the loop)...
...or it was simply because in JS the for..in loop only returns the keys, not values, i.e.
for (v in values) {
now requires
values[v]
to access the actual array value. Duh...
The way I circumvented mistake #1 is by using for..in loop instead of ...forEach() loop in the map function:
m = function () {
for (t in this.attributes['upi-tokens']) {
var token = this.attributes['upi-tokens'][t];
emit (token, { ids: [ this._id ] });
}
}
That way "this" refers to what it needs to.
Could also do:
that = this;
this.attributes['upi-tokens'].forEach( function (d) {
...
that._id...
...
}
probably would work just fine.
Hope this helps someone.