I have arrays within objects full of false values.
var drumOn = {}, bassOn = {}, synthOn = {}, keysOn = {};
var fal = [];
for(var j=0; j<16; j++){
fal.push(false);
}
for(var j=0; j<0; j++){
drumOn['s'+j] = (fal);
bassOn['s'+j] = (fal);
synthOn['s'+j] = (fal);
keysOn['s'+j] = (fal);
}
then later I try adding one true value to one array
drumOn['s'+ 0][0] = true;
This adds a true value to the first element of all the arrays within drumOn and within the other objects too.
The only other thing I'm doing with these objects is checking
if(bassOn['s' + i][j])
I was doing this with arrays within arrays and I had the same problem.
This is crazy, I've tried so many things but it makes no sense.
Copying array by value in JavaScript
for(var j=0; j<0; j++){
drumOn['s'+j] = fal.slice();
bassOn['s'+j] = fal.slice();
synthOn['s'+j] = fal.slice();
keysOn['s'+j] = fal.slice();
}
slice returns a copy of the array. In your example, all of the items are pointing to the same original array fal. You need to duplicate it.
Related
I am trying to get unique values from two arrays which looks like that:
array[{A,B,C},{C,D,E},{1,3,2},....]
both looks the same.
I tried to add them using concat and the get unique values from looping.
So I ended up with this:
function uniqueValues() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var srcSheet = ss.getSheetByName("arr1");
const array1 = srcSheet.getRange(1, 1, srcSheet.getLastRow(), srcSheet.getLastColumn()).getValues();
var srcSheet1 = ss.getSheetByName("arr2");
const array2 = srcSheet1.getRange(1, 1, srcSheet1.getLastRow(), srcSheet1.getLastColumn()).getValues();
var dodaj = array1.concat(array2);
for (var i=0; i<dodaj.length; i++) {
var listI = dodaj[i];
loopJ: for (var j=0; j<dodaj.length; j++) {
var listJ = dodaj[j];
if (listI === listJ) continue;
for (var k=listJ.length; k>=0; k--) {
if (listJ[k] !== listI[k]) continue loopJ;
}
dodaj.splice(j, 1);
}
}
var result = ss.getSheetByName("test").getRange(2, 5, dodaj.length, 3).setValues(dodaj);
//Logger.log(dodaj);
}
It was working well when array looked like this array[{A,B},{C,D}] but with three elements it started to return duplicates as well... I have no idea what can be wrong.
If I understand you correctly, you want to retrieve the unique rows from the values in arr1 and arr2. That is to say, you want to remove duplicate inner arrays from dodaj.
After using concat to merge the two arrays, you could do the following:
Use JSON.stringify() to transform each inner array to a string, in order to compare them without iterating through them.
Use the Set constructor and the spread syntax in order to remove the duplicate strings (see this answer).
Transform the strings back to arrays with JSON.parse().
Code snippet:
var dodaj = array1.concat(array2);
dodaj = [...new Set(dodaj.map(JSON.stringify))].map(JSON.parse);
var result = ss.getSheetByName("test").getRange(2, 5, dodaj.length, dodaj[0].length).setValues(dodaj);
I am trying to sort a 2D array of custom objects, inside each inner array, based on one of the properties. This sub-arrays each represent one class, the outer array all the classes in the school. My strategy is as such:
Make a copy of the arry to provide a framework with the correct number of subarrays and indeces
Pass a copy of the sub-array to variable
Iterate over that array (the class) and pull out the last name from the object (which holds a number of other pieces of data on the child) and place it in an array that will be the index
Sort the index
Iterate over the class array, find the position of the last name in the index array, and insert the object into that index into the copied 'school'.
But this is not working. In some instances, one or two objects end up in the wrong place, in other instances it completely out of order. I have tried inspecting my index and comparing it with the 2D array, but the index is correct and I can't figure out why its not working. Here is the code:
var studentsInClass = // I have a function here that returns the 2D array of classes containing custom objects
var sortedStudentsInClass = studentsInClass;
var singleClassHolder = [];
var studentIndex = [];
// each iteration is for a single class
for(var i = 0; i < studentsInClass.length; i ++){
studentIndex = [];
singleClassHolder = studentsInClass[i];
// populate the student reference index
for(var j = 0; j < singleClassHolder.length; j++){
studentIndex.push(singleClassHolder[j].ID);
}
studentIndex.sort();
// iterate through students of single class, placing them in alphabetical order
for(var k = 0; k < singleClassHolder.length; k++){
sortedStudentsInClass[i][studentIndex.indexOf(singleClassHolder[k].ID)] = singleClassHolder[k];
}
}
return sortedStudentsInClass;
}
In case the object is important:
function Child(last, first, id, classroom, serviceDays, eligibility){
this.lastName = last;
this.firstName = first;
this.ID = id;
this.class = classroom;
this.maxServiceDays = serviceDays;
this.eligibility = eligibility;
}
And just a side note, it may seem extraneous having created the new singleClassHolder variable. After I noticed I did that, I removed it and just iterated through the 2D array, but that resulted in even more elements out of place.
Make a copy of the arry
var sortedStudentsInClass = studentsInClass;
This won't make a copy. It only makes one variable reference the other in memory. They both refer to the same array in memory. See related answer here.
The easiest way to fix the code is by declaring sortedStudentsInClass as a new array.
var studentsInClass = get2DArrayOfClasses();
var sortedStudentsInClass = [];
/*...*/
for(var k = 0; k < singleClassHolder.length; k++){
sortedStudentsInClass[i] = sortedStudentsInClass[i] || [];//declare inner array, if not present
sortedStudentsInClass[i][studentIndex.indexOf(singleClassHolder[k].ID)] = singleClassHolder[k];
}
I have an JavaScript array:
var arr = [["A",["05",90]],["A",["04",240]],["A",["03",235]],["B",["00",123]],["B",["01",234]]];
I want final array to look like:
var final = [["A",[["05",90],["04",240],["03",235]]],["B",[["00",123],["01",234]]]];
The final array is formed by combining all the 2nd element of 2 dimensional array when the 1st element matches.
Please advice how can this be achieved in JavaScript
Object keys are generally the easiest way to create groups like this
var tmp = {}; // temporary grouping object
// loop over data
arr.forEach(function (item) {
// check if group started
if (!tmp.hasOwnProperty(item[0])) {
tmp[item[0]] = [];
}
// push data to group
tmp[item[0]].push(item[1]);
});
// map temp object to results array
var results = Object.keys(tmp).map(function (key) {
return [key, tmp[key]];
});
DEMO
If you start with the array you gave:
var arr = [["A",["05",90]],["A",["04",240]],["A",["03",235]],["B",["00",123]],["B",["01",234]]];
then create a new array to store the values:
var final = [];
and simply combine all of the third-level elements (such as ["05",90] and ["01",234]) of each second-level ones (such as "A" and "B") by looping through the array:
for(var i = 0; i < arr.length; i++) {
var found = false;
for(var j = 0; j < final.length; j++) {
if(arr[i][0] == final[j][0]) {
final[j][1].push(arr[i][1]);
found = true;
break;
}
}
if(!found) {
final[final.length] = [arr[i][0], [[arr[i][1][0], arr[i][1][1]]]];
}
}
This is essentially a sorting method: if the "key" is equal to one in the final array, then it adds it to that one. If not, then appends it to the end of final.
Here's the working example on JSFiddle: link.
This outputs the array:
["A", [["05", 90], ["04", 240], ["03", 235]]], ["B", [["00", 123], ["01", 234]]]
as requested.
Also, as #PaulS commented, it would be recommended to use Objects instead as Strings, to make them Key-Value pairs. But in my answer I stuck with arrays.
I want to make a loop that makes arrays automatically and assign the values to it.
The problem is how to generate the array itself automatically.
for(var attGetter=1; attGetter <= num; attGetter++){
var catesArray1 = new Array();
for(var atttGetterArray=1; atttGetterArray <= series; attGetterArray++){
idOfInput = "cate"+chartGetter+"_series"+attGetterArray;
catesArray1.push($("#"+idOfInput).val());
}
}
I want the loop to generate the array itself automatically like
catesArray1
catesArray2
catesArray3
and so on..
You need an object or an array to hold the multiple arrays you wish to create. Maybe something you are looking for is like the following?
var arrayHolder = new Array();
for(var attGetter=1; attGetter <= num; attGetter++){
var catesArray = new Array();
for(var attGetterArray=1; atttGetterArray <= series; attGetterArray++){
idOfInput = "cate"+chartGetter+"_series"+attGetterArray;
catesArray.push($("#"+idOfInput).val());
}
arrayHolder.push(catesArray);
}
If you want the arrays to be in global namespace, You can try
window['catesArray' + attGetter] = [];
...
window['catesArray' + attGetter].push(...)
Else you can create a hash object and use it to hold the reference
var obj = {};
.....
obj['catesArray' + attGetter] = [];
.....
obj['catesArray' + attGetter].push(...)
In that case you will have to create one new array that holds all the cacatesArrays from first for loop
var catesArrayContainer = new Array(); //<<<---------------------
for(var attGetter=1; attGetter <= num; attGetter++){
var catesArray = new Array();
for(var atttGetterArray=1; atttGetterArray <= series; attGetterArray++){
idOfInput = "cate"+chartGetter+"_series"+attGetterArray;
catesArray.push($("#"+idOfInput).val());
}
catesArrayContainer.push(catesArray); //<<<--------------------
}
EDIT :
This happens because the scope of variable catesArray1 was limited. When the loop enters next iteration the catesArray1 gets reinitialized, thus losing all the previously stored values...
Now in the code I have posted, we are storing every instance of catesArray1 in another array, and your values persist out side of the for loop
You can do something like this for 4 arrays of 5 elements each
yourarray=[];
for (i = 0; i <4; i++) {
temparray=[];
for (j = 0; j < 5; j++) {
temparray.push($('#'+whateverID+'_'+i+'_'+j)) //your values here
}
yourarray.push(temparray);
}
Check it on this JSFiddle. open chrome console to see array
If you want to create array within loop from index
You can use eval to evaluate javascript from strings but i wont use that unless there is no other way. you can see both above and eval method in this Fiddle. Open Chrome console to see array values
Just a comparison of using eval and 2D array
Open console in chrome while you run this jsFiddle and you will see the difference in eval and 2darray in context of this question.
You should assign them to an object. In this case, make an object variable before the first for-loop to hold all arrays:
var allArrays = {};
for(var attGetter=1; attGetter <= num; attGetter++){
var currentArray = allArrays['catesArray' + attGetter] = new Array();
for(var atttGetterArray=1; atttGetterArray <= series; attGetterArray++){
idOfInput = "cate"+chartGetter+"_series"+attGetterArray;
currentArray.push($("#"+idOfInput).val());
}
}
Instead of attempting to create & allocate dynamically named variables, I would think of this more of an array of array's if you will. In other words, create an array that holds all of the arrays you want:
var collections = []; // Literal notation for creating an array in JS
From here, it's a matter of making each value you create within this array its own array:
var n = 10; // Total amount of arrays you want
for (var i = 0; i < n; i++) {
var values = [];
// Have another loop that fills in the values array as expected
collections.push(values); // Each element at collections[i] is its own array.
}
If you truly need named elements, you could potentially do something very similar with just an object {} instead, and refer to each element by a name you create.
var collections = {}; // Literal notation for an object in JS
var n = 10; // Total amount of arrays you want
for (var i = 0; i < n; i++) {
var values = []; // Literal notation for an array in JS
// Fill in the values array as desired
var name = 'arr' + i; // How you'll refer to it in the object
collections[name] = values;
}
I suggest the former though, since it does not sound like you need to have explicit names on your arrays, but just want multiple layers of arrays.
I have a multidimensional array (retdata[R][C]) that basically looks like a spreadsheet of cells. R represents the rows, C the columns. I want to create an array of objects so that I get the following
[{retdata[1][1]:retdata[2][1],retdata[1][2]:retdata[2][2],retdata[1][3]:retdata[2][3] },
{retdata[1][1]:retdata[3][1],retdata[1][2]:retdata[3][2],retdata[1][3]:retdata[3][3] },
{retdata[1][1]:retdata[4][1],retdata[1][2]:retdata[4][2],retdata[1][3]:retdata[4][3] },
etc...
]
The resulting array should be:
[{"Col1":"dataR2C1","Col2":"dataR2C2", "Col3":"dataR2C3"},
{"Col1":"dataR3C1","Col2":"dataR3C2", "Col3":"dataR3C3"},
{"Col1":"dataR4C1","Col2":"dataR4C2", "Col3":"dataR4C3"},
etc...
]
I have tried a number of options without success. Any help would be greatly appreciated.
Here is one example I have used but it id not serializing the objects properly.
var TABLE = [];
for (var i=2; i<=rows; i++) {
var ROW = {};
for (var j=1; j<=columns; j++){
name = retdata[1][j].toString;
value = retdata[i][j].toString;
ROW += {name: value}
}
TABLE += ROW;
}
This is like a CSV-parser, the first row of your table are the keys for the line-objects. Your function would work, but you need to correct your array indices: they always start at 0, running up to n-1. Also, you need to learn a bit JavaScript syntax:
something.toString does not call the toString function on that value, but gets that function (it's just an object).
You don't need toString at all - where needed, values are automatically casted
You can't add key-value-pairs to object with a simple operator. You will need to assign the value to that property of an object, with the bracket notation. The += operator would have casted the values to strings and concatenated them.
It's the same with arrays. You could use the .push() method, or just assign to a numerical key - the javascript array object will automatically update its length.
var retdata = […];
var table = [],
keys = retdata.shift(); // get & remove the first row
for (var i=0; i<retdata.length; i++) {
var row = {};
for (var j=0; j<retdata[i].length; j++)
row[ keys[j] ] = retdata[i][j];
table[i] = row;
}
Thank you Bergi. Here is my final solution:
var TABLE = [];
for (var i=2; i<=rows; i++) {
var ROW = {};
for (var j=1; j<=columns; j++){
ROW [retdata[1][j]] = retdata[i][j];
}
TABLE[i]= ROW;
}
which works. The shift did not work as expected but above code is just what I needed. Thanks!