Related
I'm building a blog using nodejs, express and mongodb. When I go to create an article, it is saved in a database that includes all the articles. On the homepage I used an array with object to store all the articles locally and get the title, content and more from them.
I wanted to know how you can set up page navigation so that previews of only 10 articles are shown per page (first page 10 articles; second page 10 articles and so on). So I wanted to know how to set a radius of objects to take from the array (first page 1 to 10; second page 11 to 20 and so on).
Let say you have an array with 100 element and you want to split to get an array of 10 x 10 element (10 pages of 10 element)
let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100];
let pages = [];
while(arr.length > 0) {
pages.push(
arr.splice(0, 10)
);
}
console.log(arr)
console.log(pages)
Now you have an array with 10 sub-array of 10 elements each.
Image you want to print the page number 5 you have yo do something like this :
let page = 5;
let articles = pages[page-1]
for(let article of articles ) {
// render your article preview here
}
This is just an exemple to give you an idea about how to split an array into multiple pages ;)
I'm trying to compare the difference in terms of execution time in JS between running some expressions sequentially versus running the same expressions within a function call.
Given the following code:
const t1 = Date.now();
console.log(Array.from(Array(500)).map((i, idx) => idx));
const t2 = Date.now();
console.log('t=', t2 - t1, 'ms', t2, t1);
function traverseArrAndPrint() {
console.log(Array.from(Array(500)).map((i, idx) => idx));
}
const t3 = Date.now();
traverseArrAndPrint();
const t4 = Date.now();
console.log('t=', t4 - t3, 'ms', t4, t3);
Now look at the output:
node a.js
[
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99,
... 400 more items
]
t= 8 ms 1620926365937 1620926365929
[
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99,
... 400 more items
]
t= 1 ms 1620926365938 1620926365937
Why would a function call take less time to execute than the sequential expressions before it?
I'm sending Protobuf encoded data over zwssock (czmq) -- which is an websocket extension for zcmq -- to JSMQ.js after which the decoding of the protobuf data takes place.
OS: Windows
Browser: Chrome 40.0.2
ØMQ: 4.0.4
czmq: 2.2.0.
With the following problem:
the data recieved does not contain all bytes that have been send.
In fact after inspection it turns out that all bytes where recieved up to the first 0 byte.
Real example:
data send:
10,4,78,77,69,65,-110,3,19,8,101,-86,6,14,8,1,16,-40,-126,-27,-14,-12,-87,-61,2,
-16,1,1,-110,3,93,8,100,80,0,-94,6,86,34,73,36,71,80,82,77,67,44,49,48,51,50,51,
49,46,54,48,49,44,86,44,53,50,48,53,46,54,52,50,54,55,48,44,78,44,48,48,54,49,57
,46,54,49,51,57,52,55,44,69,44,52,51,46,50,44,51,54,46,52,44,50,51,48,49,49,53,4
4,44,44,83,42,54,68,32,74,9,69,80,83,71,58,52,51,50,54,-30,3,97,10,4,78,77,69,65
,18,73,36,71,80,82,77,67,44,49,48,51,50,51,49,46,54,48,49,44,86,44,53,50,48,53,4
6,54,52,50,54,55,48,44,78,44,48,48,54,49,57,46,54,49,51,57,52,55,44,69,44,52,51,
46,50,44,51,54,46,52,44,50,51,48,49,49,53,44,44,44,83,42,54,68,32,82,14,10,5,8,2
,-80,1,2,-94,6,4,8,8,16,6
data recieved:
0, 10, 4, 78, 77, 69, 65, 146, 3, 19, 8, 101, 170, 6, 14, 8, 1, 16,
137, 255, 156, 213, 244, 169, 195, 2, 240, 1, 1, 146, 3, 93, 8, 100,
80]
As you can see the byte after 80 is missing, and the squence now start with a 0 byte. I've tested with manually created data -- char* --, and everytime the same problem would occur.
The two functions below are directly taken from JSQM.js and are called by the websocket upon data recieved.
function onmessage(ev) {
if (ev.data instanceof Blob) {
var arrayBuffer;
var fileReader = new FileReader();
fileReader.onload = function () {
processFrame(this.result);
};
fileReader.readAsArrayBuffer(ev.data);
} else if (ev.data instanceof ArrayBuffer) {
processFrame(ev.data);
}
// Other message type are not supported and will just be dropped
};
function processFrame(frame) {
var view = new Uint8Array(frame);
var more = view[0];
if (incomingMessage == null) {
incomingMessage = new JSMQ.Message();
}
incomingMessage.addBuffer(frame);
// last message
if (more == 0) {
if (that.onMessage != null) {
that.onMessage(that, incomingMessage);
}
incomingMessage = null;
}
}
In the onmessage/processFrame the received data already does not contain the full bytes sequence. As you can see the received byte sequence starts with a 0, matching the [more == 0] guard.
I was not able to get wireshark to sniff the packages send, checking
if the bytes where not correctly send.
One solution would be to use bytestuffing thus removing all 0 bytes.
But surely I've must have made a mistake somewhere?
As requested:
Internally we use the c++ library of zeromq, however since the websockets
are currently een extention on the c version we need to convert to c style message. As mentioned the data has been stuffed.
void CZeroMQConnection::Send(zmq::message_t& message)
{
zmsg_t* msg = zmsg_new();
std::vector<unsigned char> rpl;
std::copy_n(reinterpret_cast<char*>(message.data()), message.size(),std::back_inserter(rpl));
// Temporary stuffing on Websockets
char stuffChar = 1;
char invalidChar = 0;
std::vector<unsigned char> stuffed;
for (auto it = rpl.begin(); it != rpl.end(); ++it)
{
if (*it == invalidChar || *it == stuffChar)
{
stuffed.push_back(stuffChar);
stuffed.push_back((*it) + 1);
}
else
stuffed.push_back(*it);
}
// As mentioned added extra 0 byte, preventing superfluos data
stuffed.push_back(0);
zmsg_push(msg, _id);
zmsg_addstr(msg, reinterpret_cast<char*> (&stuffed[0]));
zwssock_send(_socket, &msg);
}
There is is not yet a bi-directional dataflow, this will come in the near future.
Thank you somdoron,
your post uses:
zmsg_addmem(msg, buf, 226);
while i was using:
zmsg_addstr(msg, reinterpret_cast<char*> (&stuffed[0]));
which will probably interpret the input as a C string.
This solved the problem, thanx a lot!
I try to reproduce the issue with chrome (40.0.2) without success, I got the entire message including the zeros.
c code:
static char *listen_on = "tcp://127.0.0.1:86";
int main(int argc, char **argv)
{
zctx_t *ctx;
zwssock_t *sock;
char *l = argc > 1 ? argv[1] : listen_on;
ctx = zctx_new();
sock = zwssock_new_router(ctx);
zwssock_bind(sock, l);
zmsg_t* msg;
zframe_t *id;
while (!zctx_interrupted)
{
msg = zwssock_recv(sock);
if (!msg)
break;
// first message is the routing id
id = zmsg_pop(msg);
while (zmsg_size(msg) != 0)
{
char * str = zmsg_popstr(msg);
printf("%s\n", str);
free(str);
}
zmsg_destroy(&msg);
msg = zmsg_new();
zmsg_push(msg, id);
char buf[226] = { 10, 4, 78, 77, 69, 65, -110, 3, 19, 8, 101, -86, 6, 14, 8, 1, 16, -40, -126, -27, -14, -12,
-87, -61, 2, -16, 1, 1, -110, 3, 93, 8, 100, 80, 0, -94, 6, 86, 34, 73, 36, 71, 80, 82,
77, 67, 44, 49, 48, 51, 50, 51, 49, 46, 54, 48, 49, 44, 86, 44, 53, 50, 48, 53, 46, 54, 52, 50,
54, 55, 48, 44, 78, 44, 48, 48, 54, 49, 57, 46, 54, 49, 51, 57, 52, 55, 44, 69, 44, 52, 51, 46,
50, 44, 51, 54, 46, 52, 44, 50, 51, 48, 49, 49, 53, 4, 4, 44, 44, 83, 42, 54, 68, 32, 74, 9, 69, 80,
83, 71, 58, 52, 51, 50, 54, -30, 3, 97, 10, 4, 78, 77, 69, 65, 18, 73, 36, 71, 80, 82, 77, 67, 44, 49,
48, 51, 50, 51, 49, 46, 54, 48, 49, 44, 86, 44, 53, 50, 48, 53, 4, 6, 54, 52, 50, 54, 55, 48, 44, 78,
44, 48, 48, 54, 49, 57, 46, 54, 49, 51, 57, 52, 55, 44, 69, 44, 52, 51, 46, 50, 44, 51, 54, 46, 52,
44, 50, 51, 48, 49, 49, 53, 44, 44, 44, 83, 42, 54, 68, 32, 82, 14, 10, 5, 8, 2, -80, 1, 2, -94, 6, 4, 8, 8, 16, 6 };
zmsg_addmem(msg, buf, 226);
zwssock_send(sock, &msg);
}
zwssock_destroy(&sock);
zctx_destroy(&ctx);
}
and following javascript:
var dealer = new JSMQ.Dealer();
dealer.connect("ws://localhost:86");
// we must wait for the dealer to be connected before we can send messages, any messages we are trying to send
// while the dealer is not connected will be dropped
dealer.sendReady = function() {
var message = new JSMQ.Message();
message.addString("Hello");
dealer.send(message);
};
dealer.onMessage = function (message) {
// the response from the server
var buffer = message.popBuffer();
console.log(buffer.length);
console.log(buffer);
};
function send() {
var message = new JSMQ.Message();
message.addString(document.getElementById("messageTextBox").value);
dealer.send(message);
}
From an ajax call I get the following data back:
18,635,21,177,20,165,22,163,24,162,25,145,19,143,23,139,26,112,27,110,28,104,30,91,29,88,31,68,32,57,36,55,34,53,33,51,35,46,37,44,39,42,43,39,42,39,41,38,38,37,44,36,45,34,48,31,40,31,47,27,49,23,46,21,50,21,52,17,55,17,53,16,51,15,54,12,58,6,57,6,59,4,63,4,56,3,62,2,64,2,100,2,68,1,78,1,60,1,97,1,70,1,65,1,69,1,71,1
Of which every even number should be the key and every odd the value. But I have no idea how to parse it as highcharts data. Somehow I end up with the key being "slice" if I use JSON.parse and the only way I can get it to work normally is by placing it directly into the series data like this (after seperating the odd and even into seperate arrays):
[names[0] + ' years old', parseFloat(values[0])]
Which is great. But then I need to loop through the arrays somehow, pushing everything into the series data and I don't know how to do that. If I make a for loop with this data, how do I insert into the highcharts series data?
If you have that series data in an array, you can process it as follows:
var myData = [18, 635, 21, 177, 20, 165, 22, 163, 24, 162, 25, 145, 19, 143,
23, 139, 26, 112, 27, 110, 28, 104, 30, 91, 29, 88, 31, 68, 32,
57, 36, 55, 34, 53, 33, 51, 35, 46, 37, 44, 39, 42, 43, 39, 42,
39, 41, 38, 38, 37, 44, 36, 45, 34, 48, 31, 40, 31, 47, 27, 49,
23, 46, 21, 50, 21, 52, 17, 55, 17, 53, 16, 51, 15, 54, 12, 58, 6,
57, 6, 59, 4, 63, 4, 56, 3, 62, 2, 64, 2, 100, 2, 68, 1, 78, 1, 60,
1, 97, 1, 70, 1, 65, 1, 69, 1, 71, 1];
var mySeries = [];
for (var i = 0; i < myData.length; i++) {
mySeries.push([myData[i], myData[i + 1]]);
i++
}
Once you have your series data in 'mySeries', you can just set your chart data using:
series:[{
data: mySeries
}]
Alternatively, if you want to add the data after rendering the chart, you can add the series data dynamically using:
chart.series[0].setData(mySeries);
http://jsfiddle.net/Cm3Ps/ (press the 'Add My Data' button).
Actually, the function requires parameter as array of int.
Assume you get a function
drawChartFunction(data) {
// some code here
series: [{ data: data}]
}
You can try it:
array = {9,8,7,6}
var series = [];
for (var i = 0; i < array.length; i++) {
series.push([i, array.[i]]);
}
After the for executed, your series likes
0,9
1,8
2,7
3,6
Then, you call drawChartFunction(series)
So your chart is drawn by using 4 points 0 1 2 3 with their values 9 8 7 6
I've got a bunch of numbers in an array and I need to do some statistics on them. I need to know how many of each number there are in the array.
Here's the array:
myArray =
[2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 14, 14, 14, 14, 14, 14, 15, 15, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 27, 27, 28, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 33, 33, 33, 34, 34, 35, 35, 35, 35, 35, 35, 36, 36, 36, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 40, 40, 40, 41, 41, 42, 42, 42, 42, 42, 42, 43, 43, 43, 44, 44, 44, 44, 44, 45, 45, 46, 46, 46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 52, 53, 53, 53, 53, 53, 53, 53, 54, 54, 54, 55, 55, 55, 55, 55, 56, 57, 57, 57, 57, 57, 57, 57, 58, 59, 59, 59, 59, 59, 60, 60, 60, 60, 60, 61, 61, 62, 62, 63, 63, 63, 64, 64, 64, 64, 64, 65, 65, 66, 66, 66, 67, 67, 67, 68, 68, 68, 69, 69, 69, 69, 69, 69, 70, 70, 71, 71, 71, 71, 71, 71, 71, 72, 73, 73, 73, 73, 74, 74, 74, 75, 75, 75, 76, 77, 78, 78, 79, 79, 80, 80, 81, 81, 81, 81, 81, 82, 82, 82, 82, 83, 83, 83, 83, 84, 84, 84, 85, 85, 85, 85, 85, 86, 86, 86, 86, 86, 86, 87, 87, 87, 88, 88, 89, 89, 90, 90, 91, 91, 91, 92, 93, 94, 95, 95, 95, 95, 95, 96, 96, 96, 96, 97, 97, 99, 99, 99, 99, 99, 101, 101, 102, 102, 103, 103, 105, 105, 105, 106, 107, 107, 108, 108, 109, 109, 109, 109, 110, 112, 112, 113, 113, 113, 114, 114, 115, 116, 116, 117, 118, 120, 121, 121, 121, 122, 122, 123, 123, 123, 124, 124, 124, 124, 125, 126, 127, 128, 129, 130, 130, 131, 131, 131, 131, 132, 133, 133, 134, 134, 134, 136, 136, 136, 136, 137, 137, 137, 138, 138, 138, 139, 139, 139, 140, 141, 141, 142, 142, 143, 144, 144, 144, 144, 145, 150, 150, 153, 155, 159, 160, 160, 161, 162, 164, 164, 166, 176, 180, 180, 180, 181, 181, 187, 191, 192, 193, 194, 197, 200, 203, 211, 216, 224, 251, 280, 333]
Here's what I'm using to parse through it currently (which is not working very well):
for (var key in myArray){
var obj = myArray[key];
var count = 0;
while(obj < 30){
myArrayStats[0] = count;
obj++;
}
while(obj > 30 && obj < 40){
myArrayStats[1] = count;
obj++;
}
//etc....
}
Creating a new array using object literals would be much nicer and easier to use, but I'm not sure how to do it.
This just works whether your array is sorted or not, but it shouldn't be much slower than any algorithm that takes advantage of the fact that it is sorted anyways:
var myArrayStats = [];
for(var i = myArray.length; i--;)
myArrayStats[myArray[i]] = (myArrayStats[myArray[i]] || 0) + 1;
console.log(myArrayStats[6]); // Outputs 7
console.log(myArrayStats[10]); // Outputs 5
console.log(myArrayStats[20]); // Outputs 5
If you want to do this for only a portion of the original array than use slice() to get the portion of the array you want and then do the same thing as above on that array:
var mySubArray = myArray.slice(0,30);
var myArrayStats = [];
for(var i = mySubArray.length; i--;)
myArrayStats[mySubArray[i]] = (myArrayStats[mySubArray[i]] || 0) + 1;
console.log(myArrayStats[6]); // Outputs 7
console.log(myArrayStats[9]); // Outputs 7
console.log(myArrayStats[10]); // Outputs undefined
It sounds like you have equally spaced bins and want to count how many values fall in each. Since this question was tagged with jQuery, let's use a utility function from that to avoid an explicit loop to show another way to do things. (I guess PaulPRO's approach is superior though.)
function hist(values, min, max, numBins) {
var bins = [];
var range = max - min;
jQuery.each(values, function(i, value) {
var bin = Math.floor(numBins * (value - min) / range);
bin = Math.min(Math.max(bin, -1), numBins) + 1;
bins[bin] = (bins[bin] || 0) + 1;
});
return bins;
}
We can exercise the above code with the following:
function consoleHist(values, min, max, numBins) {
var bins = hist(values, min, max, numBins);
var step = (max - min) / numBins;
jQuery.each(bins, function(i, count) {
var lower = (i - 1) * step + min;
var upper = lower + step;
if (lower < min) {
lower = -Infinity;
}
if (upper > max) {
upper = Infinity;
}
console.log('[' + lower + ', ' + upper + '): ' + (count || 0));
});
}
consoleHist([-10, 0, 11, 29, 30, 59, 60, 1000], 0, 60, 2);
Produces the following output on the console:
[-Infinity, 0): 1
[0, 30): 3
[30, 60): 2
[60, Infinity): 2
myArray = [2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 8,
8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11,
11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 14, 14]
for (var a = myArray, b = {}, i = 0; i < myArray.length; i++) b[a[i]] ? b[a[i]]++ : b[a[i]] = 1;
console.log(JSON.stringify(Object.keys(b)
.map(function(c) {
return [c, b[c]]
})));