I want to write a function that takes an array such as:
var columns = ['distance', 'times', 'acceleration']
Then from this array, I want to generate something like this:
[{id: id_0, distance: 0, times: 0, acceleration: 0}, {id: id_1, distance: 1, times: 1, acceleration: 1}]
Notice that we have 2 objects here, but I want it to be whatever number I pass in to my parameter. Here is what I have:
generateData: function(rows, columns) {
var generatedData = [];
for (var i = 0, rowLen = rows.length; i < rowLen; i++) {
for (var n = 0; i < columns.length; n++) {
// not sure how to construct an object here from looping through my columns array
generatedData.push({
id: 'id_ + n',
// confused here
});
}
return generatedData;
}
}
This is the perfect place to dynamically create your own function. Try this:
function createArrayOfObjects(columns, count) {
var objectProps = new Array(columns.length);
for (var i = 0; i < columns.length; i++){
//":j" will be the variable j inside the dynamic function
objectProps[i] = columns[i] + ":j";
}
var funcBody = "var arr = new Array(count);" +
"for(var j = 0; j < count; j++){" +
"arr[j] = {" + objectProps.join(',') + "};" +
"}" +
"return arr;";
//Create a new function and call it with count as the parameter, returning the results
return new Function("count", funcBody)(count);
}
var count = 10;
var columns = ['distance', 'times', 'acceleration'];
createArrayOfObjects(columns.concat('id'), count);
This has the benefit of only having to loop over the columns array once where other solutions require nested loops.
JSPerf
I am giving you away the initial non-optimized solution. Its upto you to do the optimizations.
generateData: function(rows, columns) {
var generatedData = [];
for (var i = 0; i < rows.length; i++) {
var myObj = {};
myObj["id_" + i] = i;
for (var n = 0; n < columns.length; n++) {
myObj[columns[n]] = i;
}
generatedData.push(myObj);
}
return generatedData;
}
A functional approach that will take the object properties from the passed in array, instead of hard-coding them, might look something like this inside the for loop to populate an array named 'rows' with property names coming from the values of an array named 'cols':
cols.forEach(function(cv, ci, ca) { rows[ri][cv] = ri; });
See the snippet for a full example. Note that, in this example, I'm just shoving the current index of "rows" into the object as the property value.
var columns = ['distance', 'times', 'acceleration'];
function generateData(numRows, cols) {
rows = new Array(numRows);
for(ri=0; ri < rows.length; ri++) {
rows[ri] = { id: ri };
cols.forEach(function(cv, ci, ca) {
rows[ri][cv] = ri;
});
}
return rows;
}
data = generateData(5, columns);
console.log(data);
Related
I'm trying to make my 2d matrix to have numbers which continue on the new row
var myMatrix = [];
var row = 5;
var colom = 3;
for (var i = 0; i < rows; i++) {
var toto = 1;
myMatrix[i] = [i];
for (var j = 0; j < colom; j++) {
myMatrix[i][j] = [i + j];
}
}
console.log(myMatrix);
I'm trying to make it print numbers like this:
123
456
789 and etc...
but without success:/
can someone help and also give a video or site with examples where i can learn more about that kind of stuff?
First, a look at what your code is doing:
const myMatrix = [];
const rows = 5;
const columns = 3;
for (var i = 0; i < rows; i++) {
myMatrix[i] = [i];
for (var j = 0; j < columns; j++) {
myMatrix[i][j] = [i+j];
}
}
console.log(myMatrix);
You have a typo in your row/rows variable name. Ignoring that though...
Your myMatrix[i] line is creating an array at i, which is then being set to an array with a value of i. Just this creates a wonky mash-up , where each "row" gets an array with it's row number as the first value, something like this:
[[0], [1], [2], [3], [4]]
Your inner loop then adds a value to that array at the place and adds i+j together, but puts that inside of an array, which isn't what you want, so you get something like this:
[
[[0], [1], [2]], // i = 0
[[1], [2], [3]], // i = 1
[[2], [3], [4]], // i = 2
// ... etc
]
Also note that you are replacing that first [i] anyways, so don't set it like that, just make it an empty array [].
What you want is something like this:
const myMatrix = [];
const rows = 5;
const columns = 3;
for (var i = 0; i < rows; i++) {
myMatrix[i] = [];
for (var j = 0; j < columns; j++) {
myMatrix[i][j] = (i*columns)+j;
}
}
console.log(myMatrix);
There were three changes to your code:
Make the [i] and []. It doesn't hurt anything, but [i] also doesn't make sense.
Take the i+j part out of the array, you just want a value there.
When you add i, multiply it by columns so it doesn't reset every time: (i*columns)+j
This will give you a nice output, starting with 0. If you want it start at 1, just add one to your value:
const myMatrix = [];
const rows = 5;
const columns = 3;
for (var i = 0; i < rows; i++) {
myMatrix[i] = [];
for (var j = 0; j < columns; j++) {
myMatrix[i][j] = (i*columns)+j+1;
}
}
console.log(myMatrix);
Use i * columns + j ... and I have to add up to 30 chars for padding
What I'm working on is a menu that auto updates its entries based on an array length. It adds groups of 10 objects' properties (in this case "IDnumbers") to the menu if a new object is added to the array.
var arraysOfObject = [], obj = {"IDNumber": ""};
for(i = 0; i<42; i++){
arraysOfObject.push({"IDNumber": "Number " + i});}
Above is the array holding 42 objects with a specific property.
var array2 = [];
var leftOver = arraysOfObject.length % 10;
var groupsOfTen = (arraysOfObject.length - leftOver)/10;
for (var i = 0; i < groupsOfTen; i++) {
array2.push([]);
for (var j = i*10; j < i*10 + 10; j++)
array2[i].push(arraysOfObject[j]["IDNumber"]);
}
//now the leftover
if (leftOver > 0) {
array2.push([]);
for (var i = groupsOfTen*10; i < arraysOfObject.length; i++)
array2[array2.length-1].push(arraysOfObject[i]["IDNumber"]);
}
The array2 above is the array that stores all the possible arrays that can be grouped by 10 from arraysOfObject. In this case there are 5 inside of it, because 4 arrays holds 40 objects, and 1 array holds the 2 remainders.
That all works fine, but placing the array2 inside the menu displays all possible IDnumbers grouped together, but not grouped individually. I have to declare each possible array inside of it like so sets = [array2[0], array2[1], array2[2], array2[3], array2[4]]; If there's a 6th possible array because object #51 has been added to arraysOfObject, I have to input it with array2[5].
I don't want it to depend on my input, but that it knows the number of possible arrays and that it displays it automatically in sets. How do I do that?
var gui = new dat.GUI();
var guiData = function() {
this.message = "Dat.Gui menu";
this.system = 0;
this.Sets = 0;
};
var data = new guiData();
sets = [array2[0], array2[1], array2[2], array2[3], array2[4], array2[5]];
gui.add(data, 'message', 'Dat.Gui Menu!');
gui.add(data, 'system', {
"1": 0,
"2": 1,
"3": 2,
"4": 3,
"5": 4,
"6": 5,
}).name('system #').onChange(function(value) {
updateSets(value);
});
gui.add(data, 'Sets', sets[0]).onChange();
function updateSets(id) {
var controller = gui.__controllers[2];
controller.remove();
gui.add(data, 'Sets', sets[id]).onChange();
data.Sets = 0;
gui.__controllers[2].updateDisplay();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.1/dat.gui.min.js"></script>
<script>
var arraysOfObject = [], obj = {"IDNumber": ""};
for(i = 0; i<42; i++){
arraysOfObject.push({"IDNumber": "Number " + i});}
var array2 = [];
var leftOver = arraysOfObject.length % 10;
var groupsOfTen = (arraysOfObject.length - leftOver)/10;
for (var i = 0; i < groupsOfTen; i++) {
array2.push([]);
for (var j = i*10; j < i*10 + 10; j++)
array2[i].push(arraysOfObject[j]["IDNumber"]);
}
//now take care of the leftover
if (leftOver > 0) {
array2.push([]);
for (var i = groupsOfTen*10; i < arraysOfObject.length; i++)
array2[array2.length-1].push(arraysOfObject[i]["IDNumber"]);
}
</script>
Not the issue at hand, but I was playing around with the dat.gui as you posted it and was wondering if the dropdown could be refilled without removing/adding/etc. It seems to work with .options. (NB The initialization code makes heavy use of ES6, but can work without. The system menu is created dynamically from the sets array)
let arraysOfObject =Array.from({length:42}, (o,i) => "Number " + i),
ch =10, sets = Array.from({length:Math.ceil(arraysOfObject.length/ch)}, (a,i) => arraysOfObject.slice(i*=ch, i+ch));
var gui = new dat.GUI();
var guiData = function() {
this.message = "Dat.Gui menu";
this.system = 0;
this.Sets = 0;
};
var data = new guiData();
gui.add(data, 'message', 'Dat.Gui Menu!');
gui.add(data, 'system', sets.reduce((obj,s,i) => (obj[i+1] = i, obj), {})).name('system #').onChange(updateSets);
let controller = gui.add(data, 'Sets');
updateSets(0);
function updateSets(id) {
controller = controller.options(sets[data.Sets = id]);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.1/dat.gui.min.js"></script>
I think the easiest solution would be to use ES2015's spread operator which I don't know if you would want to use yet...
ES2015 method (demo)
sets = [...array2];
There are a few other changes in the demo to set the system variable
But after taking a closer look, you can optimize the code by using the method from this SO answer to chunk your array using slice(). Also, I'm not sure why an object was used to create array entries when it just ends up as a string... demo
var arraysOfObject = [],
system = {},
chunk = 10,
size = 92;
for (var i = 0; i < size; i++) {
arraysOfObject.push("Number " + i);
}
var sets = [];
var index = 0;
for (i = 0; i < size; i += chunk) {
sets.push(arraysOfObject.slice(i, i + chunk));
system[index + 1] = index++;
}
var gui = new dat.GUI();
var guiData = function() {
this.message = "Dat.Gui menu";
this.system = 0;
this.Sets = 0;
};
var data = new guiData();
gui.add(data, 'message', 'Dat.Gui Menu!');
gui
.add(data, 'system', system)
.name('system #')
.onChange(function(value) {
updateSets(value);
});
gui.add(data, 'Sets', sets[0]).onChange();
function updateSets(id) {
var controller = gui.__controllers[2];
controller.remove();
gui.add(data, 'Sets', sets[id]).onChange();
data.Sets = 0;
gui.__controllers[2].updateDisplay();
}
I have 2 strings and I need to construct the below result (could be JSON):
indexLine: "id,first,last,email\n"
dataLine: "555,John,Doe,jd#gmail.com"
Result: "id:555,first:john,....;
What would be the fastest way of joining alternately those 2 strings?
I wrote this - but it seems too straight forward:
function convertToObject(indexLine, dataLine) {
var obj = {};
var result = "";
for (var j = 0; j < dataLine.length; j++) {
obj[indexLine[j]] = dataLine[j]; /// add property to object
}
return JSON.stringify(obj); //-> String format;
}
Thanks.
var indexLine = "id,first,last,email";
var dataLine = "555,John,Doe,jd#gmail.com";
var indexes = indexLine.split(',');
var data = dataLine.split(',');
var result = [];
indexes.forEach(function (index, i) {
result.push(index + ':' + data[i]);
});
console.log(result.join(',')); // Outputs: id:555,first:John,last:Doe,email:jd#gmail.com
If you might have more than one instance of your object to create, you could use this code.
var newarray = [],
thing;
for(var y = 0; y < rows.length; y++){
thing = {};
for(var i = 0; i < columns.length; i++){
thing[columns[i]] = rows[y][i];
}
newarray.push(thing)
}
source
I have a function that takes two lists(each item in the two lists are the same type). It only adds item from the second list to the first list if the item in the second list does not exist in the first list. To determine if it exist in the list, I compare the property pk.
addUniqueItemsToList: function (sourceList, toAddList) {
for (var a = 0; a < toAddList.length; a++) {
var doesItemExist = false;
for (var b = 0; b < sourceList.length; b++) {
if (sourceList[b].pk == toAddList[a].pk) {
doesItemExist = true;
break;
}
}
if (!doesItemExist) {
sourceList.push(toAddList[a]);
}
}
}
Is there a way in javascript where instead of comparing pk, I can compare it to other properties of the object, by passing in the name of the property to the function? i.e., addUniqueItemsToList: function (sourceList, toAddList, propertyName)
Yes you can compare by object property directly and access properties dinamically using string as key ej array['mykey']. Also it would be better if instead of doing a for inside a for (1for - n for) create a map in order to avoid so much iterations:
Eg: Number iterations without a map when items.length = 100 & anotherItems.length = 200
100*200 = 20000 possibles iterations.
Eg. Number of iterations creating a map with items.length = 100 & anotherItems.length = 200
300 iterations.
Example of how i do it:
var items = [{_id: 1, text: "Text 1"}, {_id:2, text: "Text 2"}];
var anotherItems = [{_id: 1, text: "Text 1"}];
var mapByProperty = function(array, prop) {
var map = [];
for (var i = 0, len = array.length; i !== len; i++) {
map[array[i][prop]] = array[i];
}
return map;
};
var commonUniqueProperty = '_id';
var mappedAnotherItemsById = mapByProperty(anotherItems, commonUniqueProperty);
for(var i = 0, len = items.length; i !== len; i++) {
if(mappedAnotherItemsById[items[i][commonUniqueProperty]]) {
console.log(items[i]);
}
}
I have got a little function in javascript and I want to split an array A into a 2d array.
I will be used for square matrices. Obviously,I want it to be 2x2 if a square matrix of 2x2 is in the input and so on for 3x3 and. But I'm stuck after having read a first row.So my arr rows are repeated. Does anyone have any ideas about how I can get the next rows read properly.So,for instance,lets say I do have an array
A = [2,1,4,5,1,2,3,1,9]
Then I want my array arr to look like this:
arr = [[2,1,4],[5,1,2],[3,1,9]]
This will later be used for calculation a determinant of a matrix.
function create2Darray(clname) {
var A = document.getElementsByClassName(clname);
var arr = new Array();
var rows = Math.sqrt(A.length);
for (var i = 0; i < rows; i++) {
arr[i] = new Array();
for (var j = 0; j < rows; j++) {
arr[i][j] = A[j].value;
}
}
}
You are assigning always the same value. It should be something like:
arr[i][j] = A[i*rows+j].value;
EDIT: Here's a complete function without the DOM manipulation (that is, A is a simple array of integers):
function create2Darray(A) {
var arr = [];
var rows = Math.sqrt(A.length);
for (var i = 0; i < rows; i++) {
arr[i] = [];
for (var j = 0; j < rows; j++) {
arr[i][j] = A[i * rows + j];
}
}
return arr;
}
console.log(create2Darray([1, 2, 3, 4, 5, 6, 7, 8, 9]))