Select a record where value is max in CouchDB - mapreduce

I have a couchdb database with 156 json documents. I want to find the max of a certain value in the documents and then emit the whole document that contains that maximun value. I used this code but it doesnt seem to work. This may help you understand what i mean.
function(doc) {
var i,m;
for (i = 0; i < doc.watchers.length; i++)
m = Math.max(m,doc.watchers[i]);
for (i = 0; i < doc.watchers.length; i++)
if (m = doc.watchers[i])
emit(doc.watchers[i], doc.watchers);
}
I would also like to select the 2 top documents, that have the max value.

Just using a map function won't work because the way map/reduce works doesn't make available the complete set of keys and values to the map function at the same time.
I would use a reduce function for that. Something like this:
Map function
function(doc) {
var i,m;
for (i = 0; i < doc.watchers.length; i++) {
emit([doc._id, doc.watchers[i]], doc.watchers);
}
}
Reduce function
function(keys, values) {
var top=0;
var index=0;
for (i=0;i<keys.length;i++) {
if (keys[i][1] > top) {
top = keys[i][1];
index = i;
}
}
return({keys[index], values[index]})
}
For this strategy to work you need to query using group_level=1, so that couch passes the results grouped by document id to the map function.
I haven't tested this solution and it doesn't solve your second question yet. I can refine it if you think it goes the right way.

Related

Lookup and clear cell content google script

Sorry, I am new to scripting and this is probably a simple one to write; apologies!
I am trying to create a script that gets a range of order numbers in a column, then looks it up on another tab, and then clears a certain cell in that row.
I can get the script to look up the 1st ordernumber at the top of the list andd clear the cell I need clearing, but I cannot work out how to lookup and clear more than one order number at a time.
The logger returns all the values, so I think I need a loop, but I do not knwo where to start with that.
This is for a work project, but I have created a basic sample sheet to play around with:
https://docs.google.com/spreadsheets/d/19koKxFcOfWRz0mEaYs_lHQFgBrU19kDoeYaBY2WBe98/edit?usp=sharing
Can anyone help??
Thanks,
John
Here is the script so far:
function clearpostagecells(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName('Order Control');
var sheet2 = ss.getSheetByName('Order Database');
var find = sheet1.getRange(2,2,sheet1.getLastRow()-1).getDisplayValues();
Logger.log(find)
var values = sheet2.getRange(2, 1, sheet2.getLastRow()-1).getDisplayValues();
for (var i = 0; i < values.length; i++) {
var row = "";
for (var j = 0; j < values[i].length; j++) {
if (values[i][j] == find) {
row = i+2;
sheet2.getRange(row,7).clearContent();
}
}
}}

What is the most efficient way to compare two QStringList in QT?

I have two String Lists and I already have a function that compares two lists to find out which elements of list 2 do not exist in list 1. This block of code works, but maybe it is not the best way to achieve it, there are any other way to get the same result without performing so many iterations with nested loops?
QStringList list1 = {"12420", "23445", "8990", "09890", "32184", "31111"};
QStringList list2 = {"8991", "09890", "32184", "34213"};
QStringList list3;
for (int i = 0; i < list2.size(); ++i) {
bool exists = false;
for (int j = 0; j < list1.size(); ++j) {
if(list2[i] == list1[j]){
exists = true;
break;
}
}
if(!exists) list3.append(list2[i]);
}
qDebug() << list3;
output: ("8991", "34213")
Perhaps this small example does not seem like a problem since the lists are very small. But there might be a case where both lists contain a lot of data.
I need to compare these two lists because within my app, every time a button is clicked, it fetches an existing dataset, then runs a function that generates a new data (including existing ones, such as a data refresh), so I need to get only those that are new and didn't exist before. It might sound like strange behavior, but this is how the app works and I'm just trying to implement a new feature, so I can't change this behavior.
If you switch to QSet<QString>, your code snippet boils down to:
auto diff = set2 - set1;
If the input and output data structures must be QStringLists, you can still do the intermediate computation with QSets and still come out ahead:
auto diff = (QSet::fromList(list2) - QSet::fromList(list1)).toList();

Need to clear Duplicates in a combobox in c++

Basically Title. I have a class with multiple duplicates and I need to get rid of them in my combobox but I have no idea how. Here is my code :
for (int i = 0; i < maxInventaire; i++) {
if (item[i] != NULL) {
cmb_item->Items->Add(gcnew String(item[i]->getNom().c_str()));
}
}
for (int i = 0; i < maxEmployes; i++) {
if (employe[i] != NULL) {
cmb_employe->Items->Add(gcnew String(employe[i]->getNom().c_str()));
}
}
I have more than 20 duplicates the first one. It's a list of items I am using (ex: desktop, laptop, etc) i have stored every one of them in a class with a different id, but their name remains the same, as in desktop.
There must be a way to remove duplicates in those. I have searched everywhere with no luck, I guess you guys here could help me with that.
Thank you!
The easiest way is probably to copy the names into a std::set, and then copy them out of the set into the combo box.
std::set<std::string> names;
for (int i = 0; i < maxInventaire; i++) {
if (item[i] != NULL) {
names.insert(item[i]->getNom())
}
}
for (const auto& name: names) {
cmb_item->Items->Add(gcnew String(name.c_str()));
}
You can also use std::unordered_set, but really the performance difference only becomes significant when you have vastly too many entries for a combo-box, and having the entries in alphabetical order is probably easier than some random order (which is what unordered_set will give).

Best way to run through the entire sheet looking for a text in Google Sheets

I want to create a script that needs to find a certain string and replace it automatically. I've managed to do that, but it takes over 1 minute to run through all rows and columns to find it.
This is what I'm doing now:
for (i=1; i<=rows; i++) {
for (j=1; j<=cols; j++) {
cell = content.getCell(i, j).getValue();
if (content.getCell(i, j).getFormula()) {continue;}
try {
cell = cell.replace (find, replace);
content.getCell(i, j).setValue(cell);
}
catch (err) {continue;}
}
}
The built-in method replaces a text instantly, so I assume there is a better way to approach this. Any ideas?
Instead of retrieving each cell from the sheet one by one, use getDataRange() and getValues() to get all of the data in an array in one call, then perform your search on the array.
Then, depending on if you might have live users editing at the same time your script is run or not, you can either replace the values within the array and re-write the entire sheet with setValues(), or you can use setValue() to update the specific cells with matches one by one as you are currently doing.
See:
https://developers.google.com/apps-script/reference/spreadsheet/sheet#getdatarange
https://developers.google.com/apps-script/reference/spreadsheet/range#getvalues
Try this...
for (i=1; i<=rows; i++) {
for (j=1; j<=cols; j++) {
cellLoc = content.getCell(i, j);
cellValue = cellLoc.getValue();
if (cellLoc.getFormula()) {continue;}
try {
cellValue = cellValue.replace (find, replace);
cellLoc.setValue(cell);
}
catch (err) {continue;}
}
}
I took off every instance of content.getCell(i,j) and instead stored it into cellLoc. That way every time you need content.getCell(i,j), the program doesn't have to find the cell in the content, it can just look what the value of cellLoc is. Let me know if it works and if time has improved...
Well, I don't see much difference between this approach and my first one, but it replaces all matches instantly now:
function findReplace() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getDataRange();
var values = range.getValues();
var i, j, find, replace;
find = "hello";
replace = "bravo!!";
for (i = 0; i < values.length; i++) { //Run through all rows
for (j = 0; j < values[i].length; j++) { //Run through all columns
if (values[i][j] == find){
values[i][j] = replace;
}
}
}
range.setValues(values);
}

Fetch items from array using regex

I'm using action script and I have an array with more than 400.000 strings and now i'm using a loop and apply a regex to each item of the array to check if it's valid or not. In case it's valid, i put such item in a result array.
this process take too long, so it's a nuisance because all the process must executed many times.
I've been thinking about if there is any other way (faster) i could use for applying the regex to all items without using a loop.
Anyone could give me an idea?
EDIT
Here I attach the code used:
var list:Array;
var list_total:Array = new Array;
var pattern:String = '^['+some_letters+']{'+n+'}$';
var cleanRegExp:RegExp = new RegExp(pattern, 'gi');
for (var i:int=0; i<_words.length; i++) {
list = _words[i].match(cleanRegExp);
if (list != null)
for (var j:int=0; j < list.length; j++)
list_total.push(list[j]);
}
Thanks.
This is not a complete answer, but may help you optimize your code.
Try to do operations in your loop that are as efficient as possible. Time them using the global getTimer() function so you can compare which methods are the most efficient. When measuring/comparing, you may want to trigger your code many times, so that these differences are noticeable.
// before test
var startTime:Number = getTimer();
// do the expensive operation
var endTime:Number = getTimer();
trace("operation took ", endTime - startTime, " milliseconds.");
For example, one improvement is inside a for loop, is to not query the array for it's length each time:
for (var i:int = 0; i < myArray.length; i++)
Instead, store the length in a local variable outside of the array and use that:
var length:int = myArray.length;
for (var i:int = 0; i < length; i++)
The difference is subtle, but accessing the length from the local variable will be faster than getting it from the Array.
Another thing you can test is the regular expression itself. Try to come up with alternate expressions, or use alternate functions. I don't recall the specifics, but in one project we determined (in our case) that using the RegEx.test() method was the fastest way to do a comparison like this. It's likely that this may be as quick as String.match() -- but you won't know unless you measure these things.
Grant Skinner has some awesome resources available on his site. They are worth reading. This slide show/presentation on performance is worth looking at. Use the arrow keys to change slides.
Edit
Without hearing Grant's presentation, the initial slides may not seem that interesting. However, it does get very interesting (with concrete code examples) around slide #43: http://gskinner.com/talks/quick/#43
I do not think there is any good way to avoid using a loop.
The loop could be optimized further though.
Like someone already suggested read the array length to a var so the loop doesn't have to check length each iteration.
Instead of the nested loop use concat to join the list array to the lists_total. I'm not sure if this is actually faster. I guess it depends on how many matches the regexp gets.
Here is the modified code.
var list:Array;
var list_total:Array = new Array;
var pattern:String = '^['+some_letters+']{'+n+'}$';
var cleanRegExp:RegExp = new RegExp(pattern, 'gi');
var wordsLength:int = _words.length;
for (var i:int=0; i<wordsLength; i++) {
list = _words[i].match(cleanRegExp);
if (list != null)
lists_total = lists_total.concat(list);
}