Count frequency of an year - mongodb

I'm trying to count the frequency of an year with map/reduce, here is the code
map = %Q{
function(){
emit({}, {
year: this.birthdate.getFullYear(),
count: 1
})
}
}
reduce = %Q{
function(key, values){
var agg = { }
values.forEach( function(value){
if(agg[value.year]){
agg[value.year] += value.count
} else {
agg[key] = value.count
}
})
return agg
}
}
User.map_reduce(map, reduce).out(inline: true)
and it returns
=> [{"_id"=>{}, "value"=>{"2004"=>2.0, "2002"=>1.0, "2005"=>1.0}}]
But I have a lot of years in my database, and this is just tracking 3 of then. How can I do this?

Now its working... here is the code
map = %Q{
function(){
var today = new Date()
var age = today.getFullYear() - this.birthdate.getFullYear()
var m = today.getMonth() - this.birthdate.getMonth()
if (m < 0 || (m === 0 && today.getDate() < this.birthdate.getDate()))
age--
emit(age, { count: 1 })
}
}
reduce = %Q{
function(key, values){
var sum = 0
values.forEach( function(value){
sum += value.count
})
return { count: sum }
}
}
scoped.map_reduce(map, reduce).out(inline: true)

Related

How to Convert JS Password Strength Meter to Swift

I'm trying to convert this javascript password score function to swift, so I can use the same logic on mobile as we do on web. Here is the JS fiddle with the code to test:
function scorePassword(pass) {
var score = 0;
if (!pass)
return score;
// award every unique letter until 5 repetitions
var letters = new Object();
for (var i=0; i<pass.length; i++) {
letters[pass[i]] = (letters[pass[i]] || 0) + 1;
score += 5.0 / letters[pass[i]];
}
// bonus points for mixing it up
var variations = {
digits: /\d/.test(pass),
lower: /[a-z]/.test(pass),
upper: /[A-Z]/.test(pass),
nonWords: /\W/.test(pass),
}
variationCount = 0;
for (var check in variations) {
variationCount += (variations[check] == true) ? 1 : 0;
}
score += (variationCount - 1) * 10;
return parseInt(score);
}
function checkPassStrength(pass) {
var score = scorePassword(pass);
if (score > 80)
return "Strong";
if (score > 60)
return "Good";
if (score >= 30)
return "Weak";
return "";
}
I'm having an issue in converting this part:
var letters = new Object();
for (var i=0; i<pass.length; i++) {
letters[pass[i]] = (letters[pass[i]] || 0) + 1;
score += 5.0 / letters[pass[i]];
}
I've tried to create a dictionary to store the character as key and then increment the value with each occurrences of that key, but it's not working as expected.
let string = "Testing22!"
var score = 0
var dictionary = [String.Element: Int]()
for x in string {
let value = dictionary[x] ?? 0
dictionary[x] = value + 1
score += 5 / value
}
print(dictionary) //["s": 1, "T": 1, "g": 1, "2": 2, "n": 1, "i": 1, "!": 1, "t": 1, "e": 1]
print(score)
I'm also not sure of the most efficient way to handle the regex checks for the bonus points section.
I'd port it over to swift like this, I'm sure there are some improvements to be made, but thats a quick conversion:
func scorePassword(_ inputString: String?) -> Double {
var score: Double = 0
guard let string = inputString, !string.isEmpty else { return score }
// award every unique letter until 5 repetitions
let countedSet = NSCountedSet()
for x in string {
countedSet.add(x)
score += 5.0 / Double(countedSet.count(for: x))
}
// bonus points for mixing it up
let variations = [
"^(?=.*[0-9]).*$",
"^(?=.*[a-z]).*$",
"^(?=.*[A-Z]).*$",
"^(?=.*\\W).*$"
]
var variationCount: Double = 0
for check in variations {
print(string.testRegex(check))
variationCount += string.testRegex(check) ? 1 : 0
}
score += (variationCount - 1) * 10
return floor(score)
}
func checkPassStrength(_ inputString: String?) -> String {
let score = scorePassword(inputString)
if score > 80 {
return "Strong"
} else if score > 60 {
return "Good"
} else if score > 30 {
return "Weak"
}
return ""
}
extension String {
func testRegex(_ regex: String) -> Bool {
let test = NSPredicate(format: "SELF MATCHES %#", regex)
return test.evaluate(with: self)
}
}
You can run js code inside Swift and get the result from it, so you can share code between platforms.
let jsSource = """
function scorePassword(pass) {
var score = 0;
if (!pass)
return score;
// award every unique letter until 5 repetitions
var letters = new Object();
for (var i=0; i<pass.length; i++) {
letters[pass[i]] = (letters[pass[i]] || 0) + 1;
score += 5.0 / letters[pass[i]];
}
// bonus points for mixing it up
var variations = {
digits: /d/.test(pass),
lower: /[a-z]/.test(pass),
upper: /[A-Z]/.test(pass),
nonWords: /W/.test(pass),
}
variationCount = 0;
for (var check in variations) {
variationCount += (variations[check] == true) ? 1 : 0;
}
score += (variationCount - 1) * 10;
return parseInt(score);
}
function checkPassStrength(pass) {
var score = scorePassword(pass);
if (score > 80)
return "Strong";
if (score > 60)
return "Good";
if (score >= 30)
return "Weak";
return "";
}
"""
let context = JSContext()
context?.evaluateScript(jsSource)
let testFunction = context?.objectForKeyedSubscript("scorePassword")
let result = testFunction?.call(withArguments: ["1234"])
print("js result : " , result )
Note; I edited the part "digits: /\d/.test(pass)" to "digits: /d/.test(pass)"

How to claculate adjacent data with spark/scala

I hava a RDD,the RDD type is Tuple2(value,timestamp),value is 1 or 0 , timestamp is a sequential, and a variable limitTime=4. When I map the RDD, if the value is 1 the output value from current timestamp to (timestamp +limitTime) is 1 ,else current value is 0, I call it is period. But there is a special case,when the value is 1 and its timestamp is in period,then it is ignored, the current value of output is 0
input : (0,0),(1,1),(0,3),(0,5),(0,7),(0,8),(0,10),(1,12),(0,14),(0,15)
expected output :(0,0),(1,1),(1,3),(1,5),(0,7),(0,8),(0,10),(1,12),(1,14),(1,15)
special input2: (0,0),(1,1),(0,3),(1,5),(0,7),(1,8),(0,10),(1,12),(0,14),(0,15)
expected output2:(0,0),(1,1),(1,3),(1,5),(0,7),(1,8),(1,10),(1,12),(0,14),(0,15)
this is my try:
var limitTime=4
var startTime= -limitTime
val rdd=sc.parallelize(List((0,0),(1,1),(0,3),(1,5),(0,7),(1,8),(0,10),(1,12),(0,14),(0,15)),4)
val results=rdd.mapPartitions(parIter => {
var resultIter = new ArrayBuffer[Tuple2[Int,Int]]()
while (parIter.hasNext) {
val iter = parIter.next()
if(iter._1==1){
if(iter._2<=startTime+limitTime&&iter._2!=0&&iter._2>=startTime){
resultIter.append(iter)
}else{
resultIter.append(iter)
startTime=iter._2
}
}else{
if(iter._2<=startTime+limitTime&&iter._2!=0&&iter._2>=startTime){
resultIter.append((1,iter._2))
}else{
resultIter.append(iter)
}
}
}
resultIter.toIterator
})
results.collect().foreach(println)
it's so inefficient,how can I get the same result without array?
Following code should work for both of your cases.
var limitTime=3
var first = true
var previousValue = 0
val rdd=sc.parallelize(List((0,0),(1,1),(0,3),(0,5),(0,7),(0,8),(0,10),(1,12),(0,14),(0,15)), 4)
val tempResult = rdd.collect.map(pair => {
if(first){
first = false
previousValue = pair._1
(pair._1, pair._2)
}
else {
if ((pair._1 == 1 || previousValue == 1) && limitTime > 0) {
limitTime -= 1
previousValue = 1
(1, pair._2)
}
else {
if (limitTime == 0) limitTime = 3
previousValue = pair._1
(pair._1, pair._2)
}
}
})
tempResult.foreach(print)
If it doesn't please let me know

Why are my array's objects being destroyed on meteor insert?

This might have to do with me updating Meteor this morning.
Anyway here is some code:
//this returns Words properly
console.log('splitter', splitSentenceIntoWordsForward(sentence))
var wordsForward = splitSentenceIntoWordsForward(sentence)
//if I remove this line then everything works.
UserSentences.insert({user: Meteor.userId(), words: wordsForward})
//If I don't remove the line above, this prints an array of empty objects like this: [ { }, { } ]
console.log("wordsForward new", wordsForward, JSON.stringify(wordsForward))
It appears that insert is destroying the objects in the array somehow.
My original code has been working for weeks. Only this morning has it stopped. (There are other things besides meteor update that could be involved. I have added simpleschema and collection2. I also change some publish methods, but this code is fully run on the server.
Here is more code:
UserSentences = new Mongo.Collection('userSentences')
Schemas.UserSentences = new SimpleSchema({
words: {
type: [Object],
label: 'Words',
optional: false
},
user: {
type: String,
label: 'user id',
optional: false
}
})
UserSentences.attachSchema(Schemas.UserSentences)
Meteor.methods({
createArticle: function (text, title, share) {
var article = {}
var wordsArray = []
article.title = title
article.userID = Meteor.userId()
article.text = text
article.public = share
var id = Articles.insert(article)
article.paragraphs = []
var paragraphs = splitArticleIntoParagraphs(text)
console.log("paragraphs", paragraphs)
paragraphs = paragraphs.filter(String)
console.log('paragraphs w/o empties', paragraphs)
_.each(paragraphs, function (paragraph, p) {
// console.log("paragraph", paragraph)
article.paragraphs[p] = {}
article.paragraphs[p].read = false
article.paragraphs[p].text = paragraph
article.paragraphs[p].index = p
// console.log("paragraphs[p]", article.paragraphs[p])
var sentences = splitParagraphIntoSentences(paragraph)
article.paragraphs[p].sentences = []
_.each(sentences, function (sentence, s) {
if (sentence !== "") {
article.paragraphs[p].sentences[s] = {}
// console.log("sentence", sentence)
article.paragraphs[p].sentences[s].text = sentence
article.paragraphs[p].sentences[s].read = false
// console.log("paragraphs[p].sentences[s]", article.paragraphs[p].sentences[s])
//console.log('splitter', splitSentenceIntoWordsForward(sentence))
var wordsForward = splitSentenceIntoWordsForward(sentence)
UserSentences.insert({user: Meteor.userId(), words: JSON.parse(JSON.stringify(wordsForward))})
// console.log("wordsForward new", wordsForward, JSON.stringify(wordsForward))
article.paragraphs[p].sentences[s].forward = {}
article.paragraphs[p].sentences[s].forward.words = wordsForward
// console.log('wordsForward', JSON.stringify(wordsForward))
// var wordsReverse = splitSentenceIntoWordsReverse(sentence)
_.each(wordsForward, function (word, w) {
if (word) {
wordsArray.push(word._id)
// console.log('this word should split', word)
_.each(word.simplified.split(""), function (character) {
console.log(character)
wordsArray.push(Words.findOne({simplified: character})._id)
})
article.paragraphs[p].sentences[s].forward.words[w] = {}
article.paragraphs[p].sentences[s].forward.words[w].wordID = word._id
// article.paragraphs[p].sentences[s].forward.words[w].simplified = word.simplified
// article.paragraphs[p].sentences[s].forward.words[w].trad = word.trad
// console.log("word.simplified", word.simplified)
var characters = word.simplified.split('')
// console.log("characters", characters)
article.paragraphs[p].sentences[s].forward.words[w].characters = []
/**/
_.each(characters, function (character, c) {
if (character) {
// console.log("character", character, p, s, w, c)
article.paragraphs[p].sentences[s].forward.words[w].characters[c] = {}
article.paragraphs[p].sentences[s].forward.words[w].characters[c].text = character
article.paragraphs[p].sentences[s].forward.words[w].characters[c].wordID = Words.findOne({simplified: character})._id
}
})
}
})
}
})
})
console.log("done")
article.words = wordsArray
article.finishedCreating = true
Articles.update({_id: id}, {
$set: {
paragraphs: article.paragraphs,
words: wordsArray,
finishedCreating: true
}
}, {bypassCollection2: true})
return id
}
})
var splitSentenceIntoWordsForward = function (string) { // DictionaryForwardMaximumMatchingOld
// console.log(new Date().toDateString())
console.log('typeof', typeof string)
var foundWordsArray = []
var position = string.length
while (position > 0) {
// console.log("while")
var index = position
var partialString = string.slice(0, index)
// console.log("partial sub: " + partialString.substring(0, 20))
var found = Words.findOne({
"simplified": partialString.substring(0, 20)
})
// console.log(partialString)
if (found) {
// console.log("found: " + found.simplified)
// if (found.pinyin == "" && foundWordsArray.length > 1) { //punctuation at beginning of sentence isn't a wrapping concern.
// console.log("found punctuation")
// foundWordsArray[foundWordsArray.length - 1].simplified = foundWordsArray[foundWordsArray.length - 1].simplified + found.simplified
// } else {
foundWordsArray.push(found)
console.log("found", found.simplified)
// }
position = position - 1
var partialStringCount = partialString.length
while (partialStringCount > 0) {
// console.log("second while")
string = string.substring(1)
partialStringCount -= 1
}
position = string.length
index = position
}
else if (partialString.length == 1) {
var newEntryID = Words.insert({
trad: partialString,
simplified: partialString,
pinyin: ""
})
foundWordsArray.push(Words.findOne({
newEntryID
}))
var partialStringCount = partialString.length
while (partialStringCount > 0) {
string = string.slice(1, string.length) //remove first character
partialStringCount -= 1
}
position = string.length
index = position //advance(string.startIndex, position)
console.log("added " + partialString)
}
else {
// console.log("else")
position = position - 1
index = position
}
}
//console.log("found: ", JSON.stringify(foundWordsArray))
// console.log(new Date().toDateString())
return foundWordsArray
}
Collection2 was causing the problem.
This is how I got around it:
UserSentences.insert({user: Meteor.userId(), words: wordsForward},
{bypassCollection2: true})

after effects - selecting render queue items via script

i'm looking for a way to select items in the render queue via script.
i'm creating a listBox that contains all the RQ items ( i need to list them in a simpler way then the RQ window, and i'm keeping the index number of each item), and i want to select from that list items and select them in the RQ.
ideas?
thanks
Dror
try{
function createUserInterface (thisObj,userInterfaceString,scriptName){
var pal = (thisObj instanceof Panel) ? thisObj : new Window("palette", scriptName,
undefined,{resizeable: true});
if (pal == null) return pal;
var UI=pal.add(userInterfaceString);
pal.layout.layout(true);
pal.layout.resize();
pal.onResizing = pal.onResize = function () {
this.layout.resize();
}
if ((pal != null) && (pal instanceof Window)) {
pal.show();
}
return UI;
};
{var res ="group {orientation:'column',\
alignment:['fill','fill'],\
alignChildren:['fill','top'],\
folderPathListbox:ListBox{\
alignment:['fill','fill'],\
properties:{\
multiline:true,\
multiselect:true,\
numberOfColumns:6,\
showHeaders:true,\
columnTitles: ['#','OM','Date','Time', 'Comp Name', 'Render Path']}\
},\
buttonGroup:Group{orientation:'row',\
alignment:['fill','bottom']\
alignChildren:['fill','bottom'],\
buttonPanel: Panel{\
text:'Actions',\
orientation: 'row',\
alignment:['fill','bottom']\
refButton: Button{text:'Refresh'}\
dupButton: Button{text:'Duplicate'}\
selButton: Button{text:'Select in RQ'}\
expButton: Button{text:'Export'}\
}\
searchPanel: Panel{\
text:'Search',\
orientation: 'row',\
searchBox: EditText{text:'search by fileName'},\
searchButton: Button{text:'Search'}, \
}\
}\
}";
}
function listRQ (rqList){
try{
var folderPathListbox = rqList;
var proj = app.project;
var totalRenderQ = proj.renderQueue.numItems;
for(var i= 1; i<=totalRenderQ; i++){
var totalOM= proj.renderQueue.item(i).numOutputModules;
for (var om= 1; om<=totalOM; om++){
var dateList, timeList, curItem;
if (proj.renderQueue.item(i).startTime != null){
var min = proj.renderQueue.item(i).startTime.getMinutes() <10 ? "0"+ proj.renderQueue.item(i).startTime.getMinutes() : proj.renderQueue.item(i).startTime.getMinutes();
var year = proj.renderQueue.item(i).startTime.getFullYear().toString().substr (-2,2);
timeList = (proj.renderQueue.item(i).startTime.getHours()-1)+":" + min;
dateList =proj.renderQueue.item(i).startTime.getDate()+"/"+(proj.renderQueue.item(i).startTime.getMonth()+1)+"/"+year ;
}else{
dateList = "not ";
timeList = "rendered";
}
curItem = folderPathListbox.add ('item', i ); // Column 1
curItem.subItems[0].text = om; // Column 2
curItem.subItems[1].text = dateList.toString(); // Column 3
curItem.subItems[2].text = timeList.toString(); // Column 4
curItem.subItems[3].text = proj.renderQueue.item(i).comp.name; // Column 5
curItem.subItems[4].text = proj.renderQueue.item(i).outputModule(om).file.toString().replace(new RegExp(",","g"), "\r").replace(new RegExp("%20","g"), " ").replace(new RegExp("%5B","g"), "[").replace(new RegExp("%5D","g"), "]"); // Column 6
}
}
}catch(err){alert(err)}
return folderPathListbox;
}
var UI = createUserInterface(this,res,"Better RQ");
var myList = UI.folderPathListbox;
var lsRq = listRQ(myList);
//~ alert(lsRq.toString());
{ // buttons action
UI.buttonGroup.buttonPanel.refButton.onClick = function () {
lsRq.removeAll();
listRQ(myList);
writeLn("all done");
}
UI.buttonGroup.buttonPanel.dupButton.onClick = function () {
var lstSlct = new Array ;
lstSlct = myList.selection;
if ( lstSlct != null){
var totalDup = lstSlct.length;
for (var i= 0; i<totalDup; i++){
var lsId = lstSlct[i].toString();
var dup = parseInt(lsId);
app.project.renderQueue.item(dup).duplicate();
writeLn("duplicated #"+dup);
}
}else{
alert ("select Something");
}
}
UI.buttonGroup.buttonPanel.selButton.onClick = function () {
app.project.renderQueue.showWindow(true) ; //shows the RQ
alert ("selButton");
}
UI.buttonGroup.buttonPanel.expButton.onClick = function () {
// var compName = myList.
alert ("expButton");
}
}
}
catch(err){
alert ("Error at line # " + err.line.toString() + "\r" + err.toString());
}

MongoDB map reduce count giving more results than a query

I have a collection users in Mongo and I execute this map reduce which I believe is the equivalent of a COUNT(*) GROUP BY origin:
> m = function() { for (i in this.membership) {
... emit( this.membership[i].platform_profile.origin, 1 );
... } }
function () {
for (i in this.membership) {
emit(this.membership[i].platform_profile.origin, 1);
}
}
> r = function( id, values ) { var result = 0;
... for ( var i = 0; i < values.length; i ++ ) { result += values[i]; }
... return result; }
function (id, values) {
var result = 0;
for (var i = 0; i < values.length; i++) {
result += values[i];
}
return result;
}
> db.users.mapReduce(m, r, {out : { inline: 1}});
{
"results" : [
{
"_id" : 0,
"value" : 15
},
{
"_id" : 1,
"value" : 449
},
...
}
But if I try to count how many documents have this field set to a specific value like 1, I get fewer results:
db.users.count({"membership.platform_profile.origin": 1});
424
What am I missing?
Are your count queries using a sparse index by any chance? My only guess there would be if some other query criteria resulted in documents absent from from index to be ignored from the count.
I recreated your schema with some fixture data and the results between map/reduce and simple count queries are in agreement:
db.users.drop();
var map = function() {
for (i in this.membership) {
emit(this.membership[i].platform_profile.origin, 1);
}
};
var reduce = function(id, values ) {
var result = 0;
for (var i = 0; i < values.length; i++) {
result += values[i];
}
return result;
}
var origins = {1: "a", 2: "b", 3: "c", 4: "d"};
for (var i = 0; i < 1000; ++i) {
var membership = [];
for (var o in origins) {
if (0 == i % o) {
membership.push({ platform_profile: { origin: origins[o] }});
}
}
db.users.save({ membership: membership });
}
db.users.mapReduce(map, reduce, {out: {inline: 1}}).results.forEach(function(result){
print(result["_id"] + ": " + result["value"]);
});
for (var o in origins) {
print(origins[o] + ": " + db.users.count({"membership.platform_profile.origin": origins[o]}));
}
Here's the output:
$ mongo --quiet mr_count.js
a: 1000
b: 500
c: 334
d: 250
a: 1000
b: 500
c: 334
d: 250
You can use the following map/reduce for the equivalent of COUNT(*) GROUP BY origin
Map/Reduce Functions :
map = function() {
if(!this.membership) return;
for (i in this.membership) {
if(!this.membership[i].platform_profile || !this.membership[i].platform_profile.origin) return;
emit(this.membership[i].platform_profile.origin, 1);
}
}
reduce = function(key, values) {
var count = 0;
for (v in values) {
count += values[v];
}
return count;
}
result = db.runCommand({
"mapreduce" : "users",
"map" : map,
"reduce" : reduce,
"out" : "users_count"
});
I had the same issue. I replaced x.length by Array.sum(x) in the reduce function (assuming you emit 1 in the map function) and it works. I agree x.length should work too, but I cannot explain why it does not.