Code:
const fs = require("fs");
const { parse } = require("csv-parse");
function getSchedule() {
let schedule = [];
fs.createReadStream("./timetable.csv")
.pipe(parse({ delimiter: ",", from_line: 2 }))
.on("data", function (row) {
let classp = "ΘΗΨ3β";
// Get all items for the students classes and put them in a variable
for (let i = 0; i < row.length; i++) {
if (row[i].includes(classp) || row[i].includes("ΓΘ2Φ5-3") || row[i].includes("ΓΘ1Μ7-3")) {
schedule.push({ number: i, text: row[i] });
}
}
// Filtering to put the items in order
for (let i = 0; i < schedule.length; i++) {
if (schedule[i + 1]) {
if (schedule[i].number > schedule[i + 1].number) {
let temp = schedule[i];
schedule[i] = schedule[i + 1];
schedule[i + 1] = temp;
}
}
}
let numberOfObjects = 8 // <-- decides number of objects in each group
// Group items from schedule into groups of 8
let groupedProducts = schedule.reduce((acc, elem, index) => {
let rowNum = Math.floor(index / numberOfObjects) + 1;
acc[`${rowNum}`] = acc[`${rowNum}`] || [];
acc[`${rowNum}`].push(elem);
return acc
}, {});
console.log(groupedProducts)
});
}
getSchedule();
Output:
{
'1': [
{ number: 3, text: 'ΓΘ1Μ7-3 / 16 / Μαθηματικά Εμβ. 4-ωρ 04ΓΘΚ' },
{ number: 4, text: 'ΘΗΨ3β / 24 / Ψηφ.Ηλεκτρονικά II Γ ΘΗΥ' },
{ number: 5, text: 'ΘΗΨ3β / 24 / Ψηφ.Ηλεκτρονικά II Γ ΘΗΥ' },
{ number: 6, text: 'ΓΘ2Φ5-3 / 53 / Φυσική ΘΓΚ3-Μ6' },
{ number: 7, text: 'ΘΗΨ3β / 11 / Νέα Ελληνικά ΘΓΚ3-Μ1 Γ' },
{ number: 8, text: 'ΘΗΨ3β / 11 / Νέα Ελληνικά ΘΓΚ3-Μ1 Γ' },
{ number: 9, text: 'ΘΗΨ3β / 138α / Θρησκευτικά ΘΓΚ3-Μ1 Γ' },
{
number: 10,
text: 'ΘΗΨ3β / 118 / Εφαρμ.Προγραμ. ΙΙΙ Γ ΘΗΨ'
}
],
.....
'5': [
{ number: 37, text: 'ΓΘ1Μ7-3 / 16 / Μαθηματικά Εμβ. 4-ωρ 04ΓΘΚ' },
{
number: 39,
text: 'ΘΗΨ3β / 112 / Μικροελ. Ρομποτική Γ ΘΗΨ'
},
{
number: 40,
text: 'ΘΗΨ3β / 118 / Εφαρμ.Προγραμ. ΙΙΙ Γ ΘΗΨ'
},
{
number: 41,
text: 'ΘΗΨ3β / 118 / Εφαρμ.Προγραμ. ΙΙΙ Γ ΘΗΨ'
}
]
}
Basically what I want is to have 8 elements in the first one and 4th one and 7 in the 2nd 3rd and 5th but currently it adds 8 in all of them and 3 or 4 in the last. I tried multiple solutions like if statements and forcing an empty element in between the last and first of each element but I didn't seem to succeed.
const fs = require("fs");
const { parse } = require("csv-parse");
function getSchedule() {
let schedule = [];
fs.createReadStream("./timetable.csv")
.pipe(parse({ delimiter: ",", from_line: 2 }))
.on("data", function (row) {
let classp = "ΘΗΨ3β";
// Get all items for the students classes and put them in a variable
for (let i = 0; i < row.length; i++) {
if (row[i].includes(classp) || row[i].includes("ΓΘ2Φ5-3") || row[i].includes("ΓΘ1Μ7-3") || row[i].includes("ΓΘ2Φ1-3")) {
schedule.push({ number: i, text: row[i] });
}
}
// Filtering to put the items in order
for (let i = 0; i < schedule.length; i++) {
if (schedule[i + 1]) {
if (schedule[i].number > schedule[i + 1].number) {
let temp = schedule[i];
schedule[i] = schedule[i + 1];
schedule[i + 1] = temp;
}
}
}
// Group items from schedule into groups of 8
let groupSizes = [8, 7, 7, 8, 7];
let start = 0;
let result = [];
for (let size of groupSizes) {
result.push(schedule.slice(start, start + size));
start += size;
}
console.log(result)
});
}
getSchedule();
Related
I'm trying to assign/place a set of numbers randomly within a new array as a pair: [1,2,3,4,5,6,7,8] should equal [[1,1],[8,8],[3,3],[7,7],[2,2],[4,4],[5,5],[6,6]]
let numbers = [1,2,3,4,5,6,7,8]
let arrayToBeFilled = [];
function assign(num) {
let randomNumber = Number(Math.floor((Math.random() * 8)));
if(arrayToBeFilled[randomNumber] == null ) {
arrayToBeFilled[randomNumber] = [num, num] ;
} else if (arrayToBeFilled[randomNumber] == Array) {
return assign(num);
} else {
console.log('Trying a new number');
}
}
for (num in numbers) {
assign(Number(num));
}
console.log(arrayToBeFilled);
return arrayToBeFilled;
Returns the array but with values missing where the recursion should have filled the array (what I'm expecting at least). See <1 empty item>.
Trying a new number
Trying a new number
Trying a new number
[ [ 0, 0 ], [ 7, 7 ], [ 5, 5 ], <1 empty item>, [ 2, 2 ], [ 1, 1 ] ]
Anyone have any idea why this is happening??
I made some edits to your code:
/* prefer functions instead of global variables */
function main() {
let numbers = [1, 2, 3, 4, 5, 6, 7, 8]
let arrayToBeFilled = [];
for (num of numbers) { /* Use 'for...of' syntax for array iteration */
assign(Number(num), arrayToBeFilled);
}
return arrayToBeFilled
}
function assign(num, arr) {
const randomNumber = Number(Math.floor((Math.random() * 8)));
if (arr[randomNumber] == null) {
arr[randomNumber] = [num, num];
} else if (Array.isArray(arr[randomNumber])) { /* Proper way to check if element is an Array type */
return assign(num, arr);
} else {
return []
}
}
console.log(main());
Here's my take. The beauty of this is of course the abstraction in form of the shuffle function which works on all arrays, and can be put away into a utility sub file.
function shuffle(a) {
// you can replace this with "let n = a" if you don't care about
// the incoming array being altered
let n = [...a];
for (let i = n.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[n[i], n[j]] = [n[j], n[i]];
}
return n;
}
let numbers = [1,2,3,4,5,6,7,8];
console.log( shuffle( numbers ).map( n => [n,n] ) );
You could create function that will randomize elements and return array of the nth length for each element using while loop.
let numbers = [1, 2, 3, 4, 5, 6, 7, 8]
function randomize(data, n) {
const result = [];
data = data.slice();
while (data.length) {
const pos = Math.floor(Math.random() * data.length);
const el = data.splice(pos, 1).pop();
result.push(Array.from(Array(n), () => el));
}
return result;
}
console.log(randomize(numbers, 2))
console.log(randomize(numbers, 4))
Try the following:
function assign(num) {
let randomNumber = Number(Math.floor((Math.random() * 8)));
if(arrayToBeFilled[randomNumber] == null ) {
arrayToBeFilled[randomNumber] = [num + 1, num + 1] ;
} else {
assign(num);
}
}
You had an else in the code which was skipping one place in the array to be filled
NON-REPEATING random numbers (https://jsfiddle.net/th3vecmg/2/)
let numbers = [1, 2, 3, 4, 5, 6, 7, 8]
let arrayToBeFilled = [];
function assign(numbers, i, size) {
if (i < size) {
assign(numbers, ++i, size);
}
var randomNumber = numbers[Math.floor(Math.random() * numbers.length)];
arrayToBeFilled.push([randomNumber, randomNumber]);
numbers.splice(numbers.indexOf(randomNumber), 1);
}
assign(numbers, 0, numbers.length - 1)
console.log(arrayToBeFilled);
REPEATING random numbers (https://jsfiddle.net/th3vecmg/3/)
let numbers = [1, 2, 3, 4, 5, 6, 7, 8]
let arrayToBeFilled = [];
function assign(numbers, i) {
let randomNumber = Number(Math.floor((Math.random() * 8)));
arrayToBeFilled[i] = [randomNumber, randomNumber];
if (i < numbers.length - 1) {
assign(numbers, ++i);
}
}
assign(numbers, 0)
console.log(arrayToBeFilled);
I have tree in array like this:
[ {val: 10,index: 0},{val: 20,index: 1},{val: 30,index: 2},{val: 40,index: 5} ]
and i making tree using indexes ( 0 is root) and my result is this:
50
\
20 30
\ /
10
indexes: ( Now i hope understand this :) )
3 4 5 6
\ / \ /
1 2
\ /
0
Now I have problem with getting tree through index from my api
When i attempt tree/0 it is okay, return this tree above but when i attempt tree/1
i only want
20
or tree/2
50
\
30
Is there any alogrithm which help me exclude unnecessary branches? Any ideas?
Best regards
As a flat array without any parent's, you really don't have a tree structure.
But tree structures in Javascript using an Object is very easy.
Below is an example ->
/*
3 4 5 6
\ / \ /
1 2
\ /
0
*/
var tree = {
index: 0,
val: 'Root',
nodes: [
{
index: 1,
val: 'Value 1',
nodes: [
{
index: 3,
val: 'Value 3'
}, {
index: 4,
val: 'Value 4'
}
]
}, {
index: 2,
val: 'Value 2',
nodes: [
{
index: 5,
val: 'Value 5'
}, {
index: 6,
val: 'Value 6'
}
]
}
]
};
function display(s) {
document.write('<div>' + s + '</div>');
}
function find(root, index) {
if (root.index === index) return root;
if (root.nodes) {
for (let l = 0; l < root.nodes.length; l ++) {
let node = root.nodes[l];
if (node.index === index) return node;
node = find(node, index);
if (node) return node;
}
}
return null;
}
function treeSize(tree) {
let size = 0;
if (tree.nodes)
for (let l = 0; l < tree.nodes.length; l ++)
size += treeSize(tree.nodes[l]);
return size + 1;
}
function showTree(name, index) {
let node = find(tree, index);
if (!node) return;
display(name + '-> Size: ' + treeSize(node));
function draw(node, indent) {
display(indent + node.val);
if (node.nodes) {
for (let l = 0; l < node.nodes.length; l ++)
draw(node.nodes[l], indent + '----');
}
}
draw(node, '');
}
showTree('Tree 0', 0);
display(' ');
showTree('Tree 2', 2);
If you define your tree in the following way,
children of index i = 2*i+1 and 2*i+2
then you can perform a depth first search to print the branches resulting from an index until it reaches the leaf, so
DFS(1) -> DFS(3)
you would get 50 and 30
DFS(i) // would call
DFS(2*i+1) and DFS(2*i+2)
function convertToRoman(num) {
var thisMap = {
1:[1],
2:[1, 1],
3:[1, 1, 1],
4:[1, 5],
5:[5],
6:[5, 1],
7:[5, 1, 1],
8:[5, 1, 1, 1],
9:[1, 10],
0:[0]
};
var numMap = {
1000:"M",
500:"D",
100:"C",
50:"L",
10:"X",
5:"V",
1:"I"
};
numArr = num.toString().split("");
var thisIndex = 1;
var tallyArr = [];
for (var i = numArr.length - 1; i >= 0; i--) {
tallyArr.unshift(thisMap[numArr[i]]);
}
thisIndex = Math.pow(10, tallyArr.length - 1);
checkArr = [];
<<<BUG HERE>>>
for (var x = 0; x < tallyArr.length; x++) {
for (var y = 0; y < tallyArr[x].length; y++) {
tallyArr[x][y] *= thisIndex;
}
thisIndex = thisIndex / 10;
}
<<</BUG HERE>>>
var finalArr = [];
for (var a = 0; a < tallyArr.length; a++) {
for (var b = 0; b < tallyArr[a].length; b++) {
finalArr.push(numMap[tallyArr[a][b]]);
}
}
finalAnswer = finalArr.join("");
return finalAnswer;
}
convertToRoman(88);
So this is my function for converting a number into a Roman Numeral in Javascript. It basically formats every number into the right format using thisMap, then uses thisIndex to multiply by either 1000, 100 or 10, and then compares to numMap to get the correct Roman Numeral.
It seems to work in most of the test cases, except with 44, 99, or 3999.
In these cases, it seems to multiply the numbers by the wrong amount, so 44 becomes XLXL, when it should be XLIV.
I think the bug is between the <<>> tags I've inserted, because that is where the numbers seem to be multiplied wrong.
However, I can't spot the problem.
Thanks.
I tried a different approach.
function convertToRoman(num) {
let arabicArray = [ 1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000, 4000, 5000, 5001]
let romanArray = ['I', 'IV', 'V', 'IX', 'X', 'XL', 'L', 'XC', 'C', 'CD', 'D', 'CM', 'M', 'MV', 'V', 'limit of 5000']
let roman = ""
loop()
function loop() {
for (let i = 0; i < arabicArray.length; i++) {
if (num < arabicArray[i]) {
roman += romanArray[i - 1]
num -= arabicArray[i - 1]
while (num != 0) {loop()} break;
}
}
}
return roman
}
console.log(convertToRoman(3))
However this gives you a limit to 5000.
Try this: x loop should run through all the length of tallyArr except the last one.
function convertToRoman(num) {
// ... code ...
for (var x = 0; x < tallyArr.length - 1; x++) {
for (var y = 0; y < tallyArr[x].length; y++) {
tallyArr[x][y] *= thisIndex;
}
thisIndex = thisIndex / 10;
}
// ... more code ...
}
Your solution seems a bit over engineered and overly complicated sometimes simpler is better and what might seem like a clever answer and looking for the overly eloquent solution can trip you up.
function convertToRoman(num) {
var output = "";
var numMap = [
{ limit: 1000, value: "M" },
{ limit: 900, value: "CM" },
{ limit: 500, value: "D" },
{ limit: 400, value: "CD" },
{ limit: 100, value: "C" },
{ limit: 90, value: "XC" },
{ limit: 50, value: "L" },
{ limit: 40, value: "XL" },
{ limit: 10, value: "X" },
{ limit: 9, value: "IX" },
{ limit: 5, value: "V" },
{ limit: 4, value: "IV" },
{ limit: 1, value: "I" }
];
for(var index = 0; index < numMap.length; index++) {
var value = numMap[index].value,
limit = numMap[index].limit;
while(num >= limit) {
output += value;
num -= limit;
}
}
return output;
}
alert(convertToRoman(1));
alert(convertToRoman(4));
alert(convertToRoman(5));
alert(convertToRoman(9));
alert(convertToRoman(10));
alert(convertToRoman(88));
alert(convertToRoman(2016));
JSFiddle
var romanNumber = [
[1, 'I'], [2, 'II'], [3, 'III'],[4, 'IV'],
[5, 'V'], [6, 'VI'],[7, 'VII'], [8, 'VIII'],
[9, 'IX'],[10, 'X']
];
function convertToRoman(number) {
if (number === 0) {
return '';
}
for (var i = 0; i < romanNumber.length; i++) {
if (number === romanNumber[i][0]) {
return romanNumber[i][1];
}
}
}
console.log(convertToRoman(1));
console.log(convertToRoman(2));
console.log(convertToRoman(3));
console.log(convertToRoman(4));
console.log(convertToRoman(5));
console.log(convertToRoman(6));
console.log(convertToRoman(7));
console.log(convertToRoman(8));
console.log(convertToRoman(9));
console.log(convertToRoman(10));
i currently have something which rolls onto a number but i'd like to change it so instead of displaying the number it rolled on, it displays the name which the number is apart of. A snippet of what i have is below:
function spin(m) {
var x = m.roll;
play_sound("roll");
var order = [1, 14, 2, 13, 3, 12, 4, 0, 11, 5, 10, 6, 9, 7, 8];
var index = 0;
for (var i = 0; i < order.length; i++) {
if (x == order[i]) {
index = i;
break
}
}
var max = 32;
var min = -32;
var w = Math.floor(m.wobble * (max - min + 1) + min);
var dist = index * 70 + 36 + w;
dist += 1050 * 5;
animStart = new Date().getTime();
vi = getVi(dist);
tf = getTf(vi);
isMoving = true;
setTimeout(function() {
finishRoll(m, tf)
}, tf);
render()
}
As you can see I have 1, 14, 2, 13 etc.
I would like it so if it rolls onto 1, 2, 3, 4, 5, 6 or 7 it shows 'Group1' instead of the number it has landed on.
The same goes with 14, 13, 12, 11, 10, 9 and 8 except i'd like it to show 'Group2' instead of the number it has landed on.
Now for 0, i'd like it so it shows 'Green' instead of 0 when it lands on it.
These are the main snippets in the file.
1.
function cd(ms, cb) {
$("#counter").finish().css("width", "100%");
$("#counter").animate({
width: "0%"
}, {
"duration": ms * 1000,
"easing": "linear",
progress: function(a, p, r) {
var c = (r / 1000).toFixed(2);
$BANNER.html("Rolling in " + c + "...");
},
complete: cb
});
}
2.
function finishRoll(m, tf) {
$BANNER.html("Rolled number " + m.roll + "!");
addHist(m.roll, m.rollid);
play_sound("finish");
for (var i = 0; i < m.nets.length; i++) {
$("#panel" + m.nets[i].lower + "-" + m.nets[i].upper).find(".total").countTo(m.nets[i].swon > 0 ? m.nets[i].swon : -m.nets[i].samount, {
"color": true,
"keep": true
});
}
var cats = [
[0, 0],
[1, 7],
[8, 14]
];
for (var i = 0; i < cats.length; i++) {
var $mytotal = $("#panel" + cats[i][0] + "-" + cats[i][1]).find(".mytotal");
if (m.roll >= cats[i][0] && m.roll <= cats[i][1]) {
$mytotal.countTo(m.won, {
"color": true,
"keep": true
});
} else {
var curr = parseFloat($mytotal.html());
if ($("#settings_dongers").is(":checked")) {
curr *= 1000;
}
$mytotal.countTo(-curr, {
"color": true,
"keep": true
});
}
}
if (m.balance != null) {
$("#balance").countTo(m.balance, {
"color": true
});
checkplus(m.balance);
}
setTimeout(function() {
cd(m.count);
$(".total,.mytotal").removeClass("text-success text-danger").html(0);
$(".betlist li").remove();
snapRender();
$(".betButton").prop("disabled", false);
showbets = true;
}, m.wait * 1000 - tf);
}
3.
function snapRender(x, wobble) {
CASEW = $("#case").width();
if (isMoving) return;
else if (typeof x === 'undefined') view(snapX);
else {
var order = [1, 14, 2, 13, 3, 12, 4, 0, 11, 5, 10, 6, 9, 7, 8];
var index = 0;
for (var i = 0; i < order.length; i++) {
if (x == order[i]) {
index = i;
break
}
}
var max = 32;
var min = -32;
var w = Math.floor(wobble * (max - min + 1) + min);
var dist = index * 70 + 36 + w;
dist += 1050 * 5;
snapX = dist;
view(snapX)
}
}
How about this?
// assumes n is always a number between 0 and 14 (inclusive)
function numberToName(n) {
if (n === 0) {
return "Green";
} else if (n < 8) {
return "Group1";
} else {
return "Group2";
}
}
Just call this with the chosen number and then use the returned text however you want.
For a website I used a grid layout. What I want is to store all items per row inside a row.
I have an overall array that is calling arrWrap = [];. Now I want to create for each row an new array, where I store each time 4 items. So a new array should be created after the third item in a row.
How do I achieve this?
I use Javascript for this project.
var arrPos = [];
for (var i = 0; i < elements.length; ++i) {
arrPos[i] = i;
console.dir(arrPos[i]);
if (arrPos[i] > 3) {
alert(arrPos[i]);
};
}
var arrWrap = [];
var steps = 4;
for (var i = 0; i < elements.length; i=i+steps) {
arrWrap.push(elements.slice(i,i+steps));
}
This proposal feature the Array.prototype.reduce and offers two solutions:
Grouped by consecutive elements dataGroupedA
[
[ 0, 1, 2 ],
[ 3, 4, 5 ],
[ 6, 7, 8 ],
[ 9, 10, 11 ],
[ 12, 13, 14 ]
]
Grouped by the 5th element dataGroupedB
[
[ 0, 5, 10 ],
[ 1, 6, 11 ],
[ 2, 7, 12 ],
[ 3, 8, 13 ],
[ 4, 9, 14 ]
]
The calculation of index is the important part. The rest is standard default assignment and pushing the actual element.
var data = Array.apply(Array, { length: 15 }).map(function (_, i) { return i; }),
dataGroupedA = data.reduce(function (r, a, i) {
var index = i / 3 | 0;
r[index] = r[index] || [];
r[index].push(a);
return r;
}, []),
dataGroupedB = data.reduce(function (r, a, i) {
var index = i % 5;
r[index] = r[index] || [];
r[index].push(a);
return r;
}, []);
document.write('<pre>' + JSON.stringify(data, 0, 4) + '</pre>');
document.write('<pre>' + JSON.stringify(dataGroupedA, 0, 4) + '</pre>');
document.write('<pre>' + JSON.stringify(dataGroupedB, 0, 4) + '</pre>');
Please use the following code:
var cIndex= 0;
var data=[];
var cars = ["Saab", "Volvo", "BMW", "a", "v", "c", "q"];
for(var i = 0; i <= 3; i++)
{
cIndex = cIndex + 3;
var row = cars.slice(cIndex -3,cIndex );
data.push(row);
}
console.log(data);