How do I accomplish this in Kendo Grid/Datasource?
I have data that looks something like this:
Month | Value
--------------
1 | 10
1 | 15
1 | 30
2 | 5
2 | 7
3 | 4
I would like to group that data by month and output it to a grid in this form:
Month | Sum(Value)
------------------
1 | 55
2 | 12
3 | 4
I don't want any group headers and collapsable groups with items on it, I just want that simple output.
How can I do that in Kendo?
I don't think out of the box kendo could get you what you are wanting. You could manually massage the data into the structure you want, and then bind that to a kendo grid.
Take your array of data, group by month, then sum up the value(s);
var g = {};
var data = myData; // Or however you get your data
for(var i = 0; i < data.length; i++) {
var obj = data[i];
if(g[obj.month] === undefined) {
g[obj.month] = obj.value;
}
else {
g[obj.month] += obj.value;
}
}
var results = [];
for(var j in g) {
if(g.hasOwnProperty(j)) {
results.push({ month: j, value: g[j]});
}
}
See sample http://jsbin.com/pipinodoca/1/edit?js,output
Related
Say I have Account Numbers, Sub-account Numbers and values in a google spreadsheet where there can be duplicate Account Numbers with different sub-acc numbers:
acc no / sub acc no / val
2 / 5 / 6
3 / 10 / 8
4 / 9 / 2
2 / 14 / 1
After I sort the whole sheet by the third column, values, it's gonna look like this:
acc no / sub acc no / val
3 / 10 / 8
2 / 5 / 6
4 / 9 / 2
2 / 14 / 1
So, what I want to do is to group all meters under the same accounts while having the original sort remain intact:
acc no / sub acc no / val
3 / 10 / 8
2 / 5 / 6
2 / 14 / 1
4 / 9 / 2
Seems like after sorting it by values, I need a script that loops through the account No column, for each cell it will check the remaining account numbers, and if there's a matching duplicate one, it's gonna get moved up.
This is what I could come up with so far:
function group(){
var sheet = SpreadsheetApp.getActiveSpreadsheet();
// find how many accounts we have
var Avals = sheet.getRange("A2:A").getValues();
var Alast = Avals.filter(String).length;
for (var i = 0; i < Alast-2; i++) {
if(Avals[i].toString() == Avals[i+1].toString()){
continue;
}
for (var j = i+2; j < Alast; j++){
if(Avals[i].toString() == Avals[j].toString()){
//move
break;
}
}
}
}
Thanks in advance!
This is a sample script. Untested. Assumes Sheet is already sorted by C column.
function group(){
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
// find how many accounts we have
//get A2:C range& values
var rng = sheet.getRange(2,1,sheet.getLastRow()-1,3);
var val = rng.getValues();
var data =[];//output array
var k=0; //data array new row count
//loop through existing rows
for(i=0;i<val.length;i++){
//if A is not empty, new k row data array = original row.
if (val[i][0]) { //value check
data[k] = val[i];
k++; //increment k to next row
//Loop through rows after current row to find next similar A value,if any
for(j=i+1;j<val.length;j++) {
if (val[i][0] == val[j][0]) { //if one of the folllowing row's A value is == current A value
data[k] =val[j].slice(0); //new k data array = j row
k++; //increment k
val[j][0] =''; //set the duplicate j row's A value to null to skip during value check
}
}
}
}
//Logger.log(data);
sheet.getRange(2,1,data.length,data[0].length).setValues(data);
}
I have the linq query that produces the result below:
var result = from x in model.SITEs
where x.SiteId == homeSite
select new { x.SiteId,
x.SiteAlloc1,
x.SiteAlloc2,
x.SiteAlloc3,
x.SiteAlloc4 });
SiteId SiteAlloc1 SiteAlloc2 SiteAlloc3 SiteAlloc4
======================================================
1 5 3 2 4
But what I need is something more like this, where the Rank is the position of the SiteId in the result.
SiteId Rank
==================
1 1
2 4
3 3
4 5
5 2
var result = from x in model.SITEs
where x.SiteId == homeSite
select new { x.SiteId,
x.SiteAlloc1,
x.SiteAlloc2,
x.SiteAlloc3,
x.SiteAlloc4 }).
Select((t,u) => new {
SiteId = t.SiteId,
SiteAlloc1 = t.SiteAlloc1,
SiteAlloc2 = t.SiteAlloc2,
SiteAlloc3 = t.SiteAlloc3,
SiteAlloc4 = t.SiteAlloc4,
Rank = u + 1));
Where u is the index (0 based, that's why I added 1), or in your case the rank and t is the selected object
I want to loop through a set of rows in a Google Spreadsheet that look like this:
XXX 123 234 234
YYY 789 098 765
ZZZ 76 123 345
End Result Needs to Be:
XXX: 123
XXX: 234
XXX: 234
YYY: 789
YYY: 098
etc.
My current code:
function loopshoplocations(){
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getRange('A4:A8').getValues();
var i=0;
for(i = 0; i < 4; i++){
return ('Shop Location: ' + data[i][0]);
}}
Alternatively with a formula
=ArrayFormula( transpose(split(query(rept(left(A2:A, 3)&" ", 3),,50000), " "))&": "
&transpose(split(query(regexreplace(A2:A, "^(.+?)\s",""),,50000), " ")))
Also see this screenshot:
This code assumes that there is a header row on row one. The data gets appended at the end of the sheet. If you want something different, the code would need to be adjusted.
function loopshoplocations() {
var data,L,outerArray,innerArray,numberOfRows,sheet,startRow;
startRow = 2;
sheet = SpreadsheetApp.getActiveSheet();
numberOfRows = sheet.getLastRow();
data = sheet.getRange(startRow,1,numberOfRows-startRow+1,4).getValues();
L = data.length;
//Logger.log(data);
outerArray = [];
var i,j;
for(i = 0; i < L; i++){
for (j=1; j<4 ; j+=1) {//Begin count at one, not zero
innerArray = [];//Reset
innerArray.push(data[i][0]);
innerArray.push(data[i][j]);
//Logger.log(innerArray)
outerArray.push(innerArray);
};
};
sheet.getRange(numberOfRows+1,1,outerArray.length,outerArray[0].length).setValues(outerArray);
};
I've been trying to work out exactly how the TED Talk homepage works. Leaving aside all the animation rubbish, I find the way that the boxes are organised is really fascinating.
At first glance it looks like the jQuery masonry plugin, bu it quickly becomes clear that it tends to create several right angle triangle shapes, but has no fixed number of columns or rows, and the final shape produced is always completely solid (no hollow parts).
My initial assumption was that the boxes (their size is predetermined by some factor on the site) were sorted randomly and then sequentially added to the grid using a few simple rules, however I can't identify what those rules might be, or how they could prevent any hollows in the final shape.
Does anyone have any idea how this works?
Could be wrong but a few observations:
Each section has 19 videos
There are 4 sizes 1 (#1), 1/4 (#2), 1/16 (#3) and 1/32 (#4)
For a given section, there are always 4(#1). The number of (#2), (#3) and (#4) can be either:
4(#1), 10(#2), 4(#3), 1(#1) = 19
4(#1), 11(#2), 4(#3), 0(#1) = 19
4(#1), 11(#2), 3(#3), 1(#1) = 19
4(#1), 12(#2), 2(#3), 1(#1) = 19
4(#1), 13(#2), 1(#3), 1(#1) = 19
As for the order:
The first row always contains 2(#1) and 4(#2)
(#4) are always at the bottom of a column
Here is the javascript code which does it (you need a html page with a div#container):
function ted_layout(settings, coordinates_array, num_elements, start_x, start_y, arrangement, remaining_elements, is_child){
var num_columns = arrangement.length;
var col = 0;
var current_x = start_x;
while( col < num_columns){
var column_x_scale = 100 / arrangement[col];
var current_column_arrangement;
if(is_child){
if(num_elements > 14){
if(column_x_scale == 50){
current_column_arrangement = random_shuffle([1, 2, 2]);
} else {
current_column_arrangement = random_shuffle([1, 2]);
}
} else if(num_elements > 10){
if(column_x_scale == 50){
current_column_arrangement = [1];
} else {
current_column_arrangement = random_shuffle([1, 2]);
}
} else{
current_column_arrangement = random_shuffle([1, 2]);
}
} else {
if(num_elements > 14){
if(column_x_scale == 25){
current_column_arrangement = [1, 1];
} else {
current_column_arrangement = [1];
}
} else if(column_x_scale == 25){
current_column_arrangement = [1, 1];
} else {
current_column_arrangement = [1];
}
}
var num_rows = current_column_arrangement.length;
var current_y = start_y;
var row = 0;
while(row < num_rows){
var numRects = current_column_arrangement[row];
var current_rectangle = 0;
var current_rectangle_x = current_x;
while( current_rectangle < numRects){
if(remaining_elements == 0){
return coordinates_array;
}
var currScale = column_x_scale/numRects;
var height = settings.height * currScale*0.01;
var width = settings.width * currScale*0.01;
if(current_rectangle == numRects-1 && row == num_rows-1 && is_child && Math.random() > 0.5){
coordinates_array.push({x: current_rectangle_x, y:current_y, w:width/2, h:height/2, scale:currScale/2*0.01*2})
}
else{
coordinates_array.push({x: current_rectangle_x, y:current_y, w:width, h:height, scale:currScale*0.01*2})
}
current_rectangle_x += width;
remaining_elements--;
current_rectangle++;
}
row++;
current_y += height;
}
current_x = current_rectangle_x;
col++;
}
if( remaining_elements > 0){
coordinates_array = ted_layout(settings, coordinates_array, num_elements, start_x, current_y, random_shuffle([2, 4, 4, 2]), remaining_elements, true);
}
return coordinates_array;
}
function generate_ted_layout(num_elements){
var settings = {
width: 640,
height: 480,
};
var coordinates_array=[];
returned = ted_layout(settings, coordinates_array, num_elements, 0, 0, random_shuffle([2, 4, 4, 2]), num_elements, false);
console.log("Returned", returned)
return returned;
}
function random_shuffle(array){
var temp;
for(var i = array.length - 1; i >= 1; i--){
var elem = Math.floor(Math.random() * (i + 1));
temp = array[elem];
array[elem] = array[i];
array[i] = temp;
}
return array;
}
function initAndLayout() {
var items = generate_ted_layout(20);
var container = $('#container'); // cache jquery object
console.log(items);
for (var i = 0; i < items.length; i++)
{
var item = items[i];
console.log(item);
$('#container').append($('<div class="item"></div>').css({'left': item.x, 'top': item.y, 'width': item.w, 'height': item.h}));
}
}
I think I've worked it out.
First of all the number of items varies substantially, I'm currently viewing a page with only 13 boxes.
To start I'll name each of the 4 sizes of blocks from largest to smallest as:
A,B,C,D
As we know the first 'row' contains two As and two vertical stacks of Bs, for example:
_______________________
| A | B | A | B |
| |___| |___|
| | B | | B |
|_______|___|_______|___|
The arrangement of these appears to be random, but the Bs are always in the same vertical pattern. Looking at this just now I realised that there are only two rows, and the second row works in the same way.
The second row is twice the height of the first, taking up the rest of the page. It is built of horizontally stacked patterns of shapes, which are (at least in part) selected randomly.
I've found 9 of these patterns of shapes, two of which are a single A or B and the rest are:
_______ _______ _______ ___ ___ _______ ___
| B | B | | A | | B | B | |C|C| | B | | A | |C|C|
|___|___| | | |___|___| | B | |___| | |
| A | | | | B | B | |___| |C|D | |
| | |_______| |___|___| |_______|
| | | B | B | | A | | B |
|_______| |___|___| | | |___|
|B |C| |B |C| | |
|___| |___| |_______|
The next question is how are these selected? There may be some clever searching to find the best configuration: for example if there are X items to be displayed we need to find a configuration with a total of X which does not exceed the width of the row.
This could be done with a metric of pattern density, which would be number of blocks divided by the width of the pattern.
I'm looking for some algorithm that for a given record with n properties with n possible values each (int, string etc) searches a number of existing records and gives back the one that matches the most properties.
Example:
A = 1
B = 1
C = 1
D = f
A | B | C | D
----+-----+-----+----
1 | 1 | 9 | f <
2 | 3 | 1 | g
3 | 4 | 2 | h
2 | 5 | 8 | j
3 | 6 | 5 | h
The first row would be the one I'm looking for, as it has the most matching values. I think it doesn't need to calculate any closeness to the values, because then row 2 might be more matching.
Loop through each row, add one to the row score of a field matches (field one has a score of 2) and when that's done, you have a resultset of scores which you can sort.
The basic algorithm could look like (in java pseudo code):
int bestMatchIdx = -1;
int currMatches = 0;
int bestMatches = 0;
for ( int row = 0 ; row < numRows ; row++ ) {
currMatches = 0;
for ( int col = 0 ; col < numCols ; col++ ) {
if ( search[col].equals( rows[ row ][ cols] ))
currMatches++;
}
if ( currMatches > bestMatches ) {
bestMatchIdx = row;
bestMatches = currMatches;
}
}
This assumes that you have an equals function to compare, and the data stored in a 2D array. 'search' is the reference row to compare all other rows against it.