Mongoid - Detect if there are results on the next page - mongoid

Using Mongoid, how can I check if given the limit/results_per_page options there is a next page ?
Suppose my scope is
MyCollection.page(#page).per(#per)
Calling .count will compute the total number of results across all pages. But how do I detect if the current page is full/empty ? Or better if the next page is empty ? Do I have to resolve the scope by calling something like to_a?

Calling .count will compute the total number of results across all pages.
Yes. And you know #page and #per. That's all you need. As long as #page * #per is less than count, you have (at least one) next page. (assuming pages start with 1 and not 0)
Example:
We have 57 elements and our page size is 20.
#page #per displaying #page*#per count have next page?
1 20 1 - 20 20 57 yes
2 20 21 - 40 40 57 yes
3 20 41 - 57 60 57 no

Related

Assigning Values to a struct from text file with unkown amount of data

I'm stuck at this where I need to find the highest average number inside a text file with an unknown amount of data.
The data inside the txt is like this
id group score
2203 1 33
5123 2 58
3323 3 92
5542 2 86
....
....
and the file keeps going.
I'm currently trying to create a struct and then store the values inside of it, but I cannot determine the size of struct since the file has unknown amount of data and it might change every run.
What I tried is this
while(!feof(fptr)) {
for(i = 0; i < sizeoffile; i++ ) { // here i should add the size or the amount of data.
fscanf(fptr,"%d %d %d",&p[i].num, &p[i].grp, &p[i].score);
}
}
I tried adding a counter inside the while loop to get the amount of data but it doesn't work. Im not sure if i need to use malloc or something else.
Example run:
code read the following file
1312 1 30
1234 1 54
2931 2 23
2394 2 99
9545 3 95
8312 3 100
8542 4 70
2341 4 56
1233 1 70
2323 1 58
output
group 3 has the highest average of 97
Code could go through the file once and determine the count of records: N and then read again, this time saving in an array of size N.
Alternative, use a linked-list.
or allocated some memory and re-allocate as needed.

Extracting data with Vlookup and checking values with Arrayformula

I need to extract data from one tab (extracted data) to another tab and validate the data in the following way:
if 0% assign 3
if from 0 till -10% assign 2
if from -10% and more assign 1
if from 0% till 10% assign 4
if from 10% and more assign 5
here is the link to the file https://docs.google.com/spreadsheets/d/1f8SFi2hNP6Anav7G7BYWyK-fasPk1pT1A2HFJblT-FI/edit?usp=sharing
I suggest you use two vlookups.
If you have a tab called 'Ranges' with the following two columns:
Percentage Result
-1000% 1
-10% 2
0% 3
10% 4
11% 5
Then the formula in cell B1 on the 'calculations' tab would be something like:
=arrayformula({"Con Potential";iferror(vlookup(vlookup(A2:A,'Extracted data'!A:D,4,0),Ranges!A:B,2,1),)})
Delete all data below cell B1 for the arrayformula to work correctly.
The second vlookup references col D on the 'Extracted data' tab because that is the percentage I think you are comparing? If not, alter 4 in the vlookup to another column.
If it helps, please see:
https://stackoverflow.com/help/someone-answers
NB: In place of Ranges!A:B you could use a fixed array:
=arrayformula({"Con Potential";iferror(vlookup(vlookup(A2:A,'Extracted data'!A:D,4,0),{-10,1;-0.1,2;0,3;0.1,4;0.11,5},2,1),)})
If you want to temporarily see the fixed array in case you want to edit any values, place this in a cell somewhere out of the way:
={-10,1;-0.1,2;0,3;0.1,4;0.11,5}
, is used to bump to a new column, ; is used as a return.
Relevance
Looking at 'Relevance' lookup from 'Position Delta' and this table in your sheet:
Since a 'position delta' value of 10 cannot both have a relevance of 5 and 4, I've made the assumption that 10 gets 5. If that is incorrect, then I'll adjust the boundaries.
Add this to cell C1 on the 'calculations' tab (clearing all cells below):
=arrayformula({"Relevance";iferror(vlookup(vlookup(calculations!A2:A,'Extracted data'!A:D,3,0),{0,5;11,4;21,3;31,2;41,1;51,0},2,1),)})
The fixed array {0,5;11,4;21,3;31,2;41,1;51,0} has these values:
0 5
11 4
21 3
31 2
41 1
51 0
If you need to change the boundaries so 10 is a 4, not 5, then change the vlookup to use this fixed range {0,5;10,4;20,3;30,2;40,1;50,0}:
0 5
10 4
20 3
30 2
40 1
50 0
vlookup is incremental and anything up to 11 will get 5, then 11 to 20 will get 4, 21 to 30 will get 3 and so on.
,1) in the vlookup at the far right gets the nearest value match until 'position delta' has reached the next boundary.

Add Countif to Array Formula (Subtotal) in Excel

I am new to array formulae and have noticed that while SUBTOTAL includes many functions, it does not feature COUNTIF (only COUNT and COUNTA).
I'm trying to figure out how I can integrate a COUNTIF-like feature to my array formula.
I have a matrix, a small subset of which looks like:
A B C D E
48 53 46 64 66
48 66 89
40 38 42 49 44
37 33 35 39 41
Thanks to the help of #Tom Shape in this post, I (he) was able to average the sum of each row in the matrix provided it had complete data (so rows 2 and 4 in the example above would not be included).
Now I would like to count the number of rows with complete data (so rows 2 and 4 would be ignored) which include at least one value above a given threshold (say 45).
In the current example, the result would be 2, since row 1 has 5/5 values > 45, and row 3 has 1 value > 45. Row 5 has values < 45 and rows 2 and 3 have partially or fully missing data, respectively.
I have recently discovered the SUMPRODUCT function and think that perhaps SUMPRODUCT(--(A1:E1 >= 45 could be useful but I'm not sure how to integrate it within Tom Sharpe's elegant code, e.g.,
=AVERAGE(IF(SUBTOTAL(2,OFFSET(A1,ROW(A1:A5)-ROW(A1),0,1,COLUMNS(A1:E1)))=COLUMNS(A1:E1),SUBTOTAL(9,OFFSET(A1,ROW(A1:A5)-ROW(A1),0,1,COLUMNS(A1:E1))),""))
Remember, I am no longer looking for the average: I want to filter rows for whether they have full data, and if they do, I want to count rows with at least 1 entry > 45.
Try the following. Enter as array formula.
=COUNT(IF(SUBTOTAL(4,OFFSET(A1,ROW(A1:A5)-ROW(A1),0,1,COLUMNS(A1:E1)))>45,IF(SUBTOTAL(2,OFFSET(A1,ROW(A1:A5)-ROW(A1),0,1,COLUMNS(A1:E1)))=COLUMNS(A1:E1),SUBTOTAL(9,OFFSET(A1,ROW(A1:A5)-ROW(A1),0,1,COLUMNS(A1:E1))))))
Data

How to identify breaks within an array of MATLAB?

I have an array in MATLAB containing elements such as
A=[12 13 14 15 30 31 32 33 58 59 60];
How can I identify breaks in values of data? For example, the above data exhibits breaks at elements 15 and 33. The elements are arranged in ascending order and have an increment of one. How can I identify the location of breaks of this pattern in an array? I have achieved this using a for and if statement (code below). Is there a better method to do so?
count=0;
for i=1:numel(A)-1
if(A(i+1)==A(i)+1)
continue;
else
count=count+1;
q(count)=i;
end
end
Good time to use diff and find those neighbouring differences that aren't equal to 1. However, this will return an array which is one less than the length of your input array because it finds pairwise differences up until the last element, so naturally there will be one less. As such, when you find the locations that aren't equal to 1, make sure you add 1 to the locations to account for this:
>> A=[12 13 14 15 30 31 32 33 58 59 60];
>> q = find(diff(A) ~= 1) + 1
q =
5 9
This tells us that locations 5 and 9 in your array is where the jump happens, and that's right for your example data.
However, if you want to find the locations before the jump happens, such as in your code, don't add 1 to the result:
>> q = find(diff(A) ~= 1)
q =
4 8

How to find subarray between min and max

I have a Sorted array .Lets assume
{4,7,9,12,23,34,56,78} Given min and max I want to find elements in array between min and max in efficient way.
Cases:min=23 and max is 78 op:{23,34,56,78}
min =10 max is 65 op:{12,23,34,56}
min 0 and max is 100 op:{4,7,9,12,23,34,56,78}
Min 30 max= 300:{34,56,78}
Min =100 max=300 :{} //empty
I want to find efficient way to do this?I am not asking code any algorithm which i can use here like DP exponential search?
Since it's sorted, you can easily find the lowest element greater than or equal to the minimum desired, by using a binary search over the entire array.
A binary search basically reduces the serch space by half with each iteration. Given your first example of 10, you start as follows with the midpoint on the 12:
0 1 2 3 4 5 6 7 <- index
4 7 9 12 23 34 56 78
^^
Since the element you're looking at is higher than 10 and the next lowest is lesser, you've found it.
Then, you can use a similar binary search but only over that section from the element you just found to the end. This time you're looking for the highest element less than or equal to the maximum desired.
On the same example as previously mentioned, you start with:
3 4 5 6 7 <- index
12 23 34 56 78
^^
Since that's less than 65 and the following one is also, you need to increase the pointer to the halfway point of 34..78:
3 4 5 6 7 <- index
12 23 34 56 78
^^
And there you have it, because that number is less and the following number is more (than 65)
Then you have the start at stop indexes (3 and 6) for extracting the values.
0 1 2 3 4 5 6 7 <- index
4 7 9 ((12 23 34 56)) 78
-----------
The time complexity of the algorithm is O(log N). Though keep in mind that this really only becomes important when dealing with larger data sets. If your data sets do consist of only about eight elements, you may as well use a linear search since (1) it'll be easier to write; and (2) the time differential will be irrelevant.
I tend not to worry about time complexity unless the operations are really expensive, the data set size gets into the thousands, or I'm having to do it thousands of times a second.
Since it is sorted, this should do:
List<Integer> subarray = new ArrayList<Integer>();
for (int n : numbers) {
if (n >= MIN && n <= MAX) subarray.add(n);
}
It's O(n) as you only look at every number once.

Resources