I am trying to create a matrix table. The values to be plugged into the matrix will be user input from an html table (basically a unique pairing table which pairs two elements at a time and for each pair a user can select which he prefers and by how much it is prefered on a scale of 1-9 using radio buttons). it is the preferences i.e. 1-9 that gets plugged into the matrix table and the number of unique pairing that detemines the lenght of the matrix.
when the matric is generated i want to have something like this:
0 1 2 3 4 sum
1 [1] [6] [2] [8] 17
2 [ ] [1] [9] [4] 15
3 [ ] [ ] [1] [7] 8
4 [ ] [ ] [ ] [1] 1
The problem is now i want to get the values of clicked radios into the matix. I know how to get it but just don't know how to fit it into the matrix. Here is the code I have for now, pls ask me questions if needed thanks:
$(function(){
var tableLenght = new Array();
$('#matrix').click(function(){
var counter = 0;
$("#riskForm tr").each(function(){
//ignores the header of the table (the title)
if(counter >=1){
tableLenght.push($(this).closest('tr').children("td:eq(1)").text());
}
counter++;
});
// get unique attributes of in our table
var uniqueList = new Array();
//push first element onto list
uniqueList.push(tableLenght[0]); //pushes current elem onto the array
var cur = tableLenght[0]; //sets first element by default
for(var i = 1; i < tableLenght.length; i++){ //loops through the whole lenght of our array
if(cur != tableLenght[i]){//checks if the current is not same as the next one
cur = tableLenght[i]; //sets the new elemt
uniqueList.push(tableLenght[i]); //pushes onto the array
}
}
alert(uniqueList); //alerts only the unique table rows in the tableLenght array
var myArray = new Array(uniqueList);
for (var i = 0; i < uniqueList; i++) {
myArray[i] = new Array(uniqueList);
for (var j = 0; j < uniqueList; j++) {
myArray[i][j] = '';
}
}
});
//to show/get the values of selected radio buttons
function showValues() {
var fields = $( ":input").serializeArray();
$( "#results" ).empty();
jQuery.each( fields, function( i, field ) {
$( "#results" ).append( field.value + " " );
});
}
$( ":checkbox, :radio" ).click( showValues );
showValues();
$('#display').click(function (n) {
document.location.href="trialIndex.php"
});
});
Your help is much appreciated!
You can push a value to an array, for example:
var a = [];
a.push(1);
a.push(2);
console.log(a); // [1, 2]
You can set it based on index:
var a = [];
a[0] = 1;
a[1] = 2;
console.log(a); // [1, 2]
To create a multi dimensional array you can simply push arrays to one array.
var a = [1,2,3];
var b = [4,5,6];
var c = [];
c.push(a);
c.push(b);
console.log(c); // [[1, 2, 3], [4, 5, 6]]
I think you are trying to implement the AHP algorithm here. It is quite complex to write the whole code here and how it'll work but here is a link of an already exiting work on AHP. Hope it helps: https://github.com/humbertoroa/ahp
Related
I am trying to create an array that I can filter by in Google Apps Script. This works when the array is made of values I take from the columns using range.getValues(), but doesn't work when I create a similar multidimensional array using a loop.
I am trying to create the array myself as opposed to getting it from the sheet as the columns that I want are not consecutive: one is the 10th column, the next is the 1st, the next is the 3rd etc.
This works and returns the full multidimensional range filtered properly:
function RunReport(){
var errorSS = SpreadsheetApp.getActive();
var enterpriseSheet = errorSS.getSheetByName('Enterprise');
var destSheet = errorSS.getSheetByName('TestSheet');
var sheetData = [];
sheetData = enterpriseSheet.getRange(1, 1, 2000, 4).getValues();
var filtered = sheetData.filter(function(dataRow){
return dataRow[0] === 'Error';
});
Logger.log(filtered);
}
This 'works' but only returns the first 'column' of the array filtered by the 'Error value' but doesn't return the other parts of the array:
function RunReport(){
var errorSS = SpreadsheetApp.getActive();
var enterpriseSheet = errorSS.getSheetByName('Enterprise');
var destSheet = errorSS.getSheetByName('TestSheet');
var sheetData = [];
var col1 = enterpriseSheet.getRange(1, 1, enterpriseSheet.getLastRow()).getValues();
var col2 = enterpriseSheet.getRange(1, 10, enterpriseSheet.getLastRow()).getValues();
var col3 = enterpriseSheet.getRange(1, 2, enterpriseSheet.getLastRow()).getValues();
var col4 = enterpriseSheet.getRange(1, 3, enterpriseSheet.getLastRow()).getValues();
for (i = 0; i < col1.length; i++)
{
sheetData.push(col1[i],col2[i],col3[i],col4[i]) ;
}
var filtered = sheetData.filter(function(dataRow){
return dataRow[0] === 'Error';
});
Logger.log(filtered);
}
any ideas on what I am doing wrong?
Issue:
You're getting a 2D array.
You're pushing a four 1D arrays.
Solution:
You need to push 4 elements as a single array.
Modified Script:
push a single array with four elements
//sheetData.push(col1[i],col2[i],col3[i],col4[i]) ;
sheetData.push([col1[i][0],col2[i][0],col3[i][0],col4[i][0]]);
Alternatively, You can splice everything in col1:
//for(i=0 ; i<col1.length ; i++)
//{ sheetData.push(col1[i],col2[i],col3[i],col4[i]) ;}
col1.map(function(e,i){
e.splice(1,0,col2[i][0],col3[i][0],col4[i][0]);
return e;
});
Logger.log(col1);
References:
2D Array
Array#filter
Array#map
Array#Splice
Im trying to swap two array elements in an array that looks like this
[18785:Object, 22260:Object, 22261:Object, 22262:Object, 22263:Object]
I used the following code:
that.moveMediumDown = function(mediumID){
var arrKeys = new Array();
for (key in that.data.medium) {
arrKeys.push(parseInt(key));
}
for (var i = 0; i < arrKeys.length; i++){
if (arrKeys[i] === parseInt(mediumID)) {
//swap Medium
var tmpMedium = that.data.medium[arrKeys[i]];
that.data.medium[arrKeys[i]] = that.data.medium[arrKeys[i + 1]];
that.data.medium[arrKeys[i + 1]] = tmpMedium;
break;
}
}
//build new array with correct ids
var tmpMediumArray = new Array();
for (var j = 0; j < arrKeys.length; j++){
tmpMediumArray[arrKeys[j]] = that.data.medium[arrKeys[j]];
}
}
The problem is when I swap the content of the two array elements, the key stays the same. But I need also to swap the key.
So i tried to build a new array with the correct keys but then I get an Array with 22263 elements. Most of them are undefined and only the 5 are correct.
Is there any method to do this without getting such a big array?
Thanks in advance for your help.
Checkout the array_flip function.
It allows you to swap keys with the elements:
array_flip( {a: 1, b: 1, c: 2} );
becomes
{1: 'b', 2: 'c'}
For some reason I'm having some serious difficulty wrapping my mind around this problem. I need this JS function that accepts 2 arrays, compares the 2, and then returns a string of the missing element. E.g. Find the element that is missing in the currentArray that was there in the previous array.
function findDeselectedItem(CurrentArray, PreviousArray){
var CurrentArrSize = CurrentArray.length;
var PrevousArrSize = PreviousArray.length;
// Then my brain gives up on me...
// I assume you have to use for-loops, but how do you compare them??
return missingElement;
}
Thank in advance! I'm not asking for code, but even just a push in the right direction or a hint might help...
Problem statement:
Find the element that is missing in the currentArray that was there in the previous array.
previousArray.filter(function(x) { // return elements in previousArray matching...
return !currentArray.includes(x); // "this element doesn't exist in currentArray"
})
(This is as bad as writing two nested for-loops, i.e. O(N2) time*). This can be made more efficient if necessary, by creating a temporary object out of currentArray, and using it as a hashtable for O(1) queries. For example:)
var inCurrent={}; currentArray.forEach(function(x){ inCurrent[x]=true });
So then we have a temporary lookup table, e.g.
previousArray = [1,2,3]
currentArray = [2,3];
inCurrent == {2:true, 3:true};
Then the function doesn't need to repeatedly search the currentArray every time which would be an O(N) substep; it can instantly check whether it's in currentArray in O(1) time. Since .filter is called N times, this results in an O(N) rather than O(N2) total time:
previousArray.filter(function(x) {
return !inCurrent[x]
})
Alternatively, here it is for-loop style:
var inCurrent = {};
var removedElements = []
for(let x of currentArray)
inCurrent[x] = true;
for(let x of previousArray)
if(!inCurrent[x])
removedElements.push(x)
//break; // alternatively just break if exactly one missing element
console.log(`the missing elements are ${removedElements}`)
Or just use modern data structures, which make the code much more obvious:
var currentSet = new Set(currentArray);
return previousArray.filter(x => !currentSet.has(x))
*(sidenote: or technically, as I illustrate here in the more general case where >1 element is deselected, O(M*N) time)
This should work. You should also consider the case where the elements of the arrays are actually arrays too. The indexOf might not work as expected then.
function findDeselectedItem(CurrentArray, PreviousArray) {
var CurrentArrSize = CurrentArray.length;
var PreviousArrSize = PreviousArray.length;
// loop through previous array
for(var j = 0; j < PreviousArrSize; j++) {
// look for same thing in new array
if (CurrentArray.indexOf(PreviousArray[j]) == -1)
return PreviousArray[j];
}
return null;
}
Take a look at underscore difference function: http://documentcloud.github.com/underscore/#difference
I know this is code but try to see the difference examples to understand the way:
var current = [1, 2, 3, 4],
prev = [1, 2, 4],
isMatch = false,
missing = null;
var i = 0, y = 0,
lenC = current.length,
lenP = prev.length;
for ( ; i < lenC; i++ ) {
isMatch = false;
for ( y = 0; y < lenP; y++ ) {
if (current[i] == prev[y]) isMatch = true;
}
if ( !isMatch ) missing = current[i]; // Current[i] isn't in prev
}
alert(missing);
Or using ECMAScript 5 indexOf:
var current = [1, 2, 3, 4],
prev = [1, 2, 4],
missing = null;
var i = 0,
lenC = current.length;
for ( ; i < lenC; i++ ) {
if ( prev.indexOf(current[i]) == -1 ) missing = current[i]; // Current[i] isn't in prev
}
alert(missing);
And with while
var current = [1, 2, 3, 4],
prev = [1, 2, 4],
missing = null,
i = current.length;
while(i) {
missing = ( ~prev.indexOf(current[--i]) ) ? missing : current[i];
}
alert(missing);
This is my approach(works for duplicate entries too):-
//here 2nd argument is actually the current array
function(previousArray, currentArray) {
var hashtable=[];
//store occurances of elements in 2nd array in hashtable
for(var i in currentArray){
if(hashtable[currentArray[i]]){
hashtable[currentArray[i]]+=1; //add 1 for duplicate letters
}else{
hashtable[currentArray[i]]=1; //if not present in hashtable assign 1
}
}
for(var i in previousArray){
if(hashtable[previousArray[i]]===0 || hashtable[previousArray[i]] === undefined){ //if entry is 0 or undefined(means element not present)
return previousArray[i]; //returning the missing element
}
else{
hashtable[previousArray[i]]-=1; //reduce count by 1
}
}
}
Logic is that i have created a blank array called hashtable. We iterate currentArray first and use the elements as index and values as counts starting from 1(this helps in situations when there are duplicate entries). Then we iterate through previousArray and look for indexes, if they match we reduce the value count by 1. If an element of 2nd array doesnt exist at all then our undefined check condition fires and we return it. If duplicates exists, they are decremented by 1 each time and when 0 is encountered, that elment is returned as missing element.
I have a table 10 rows, 10 columns. I want to define an array where I can place a value at e.g. pos. row 5, column 3.
The value itself is an array with more entries. And the entry of this array is also an array.
Example:
Row 1, column 1:
My text 1, Link to text 1
My text 2, Link to text 2
Row 4, column 5:
My text 3, Link to text 3
Row 6, column 2:
My text 1, Link to text 1
My text 2, Link to text 2
My text 3, Link to text 3
My text 4, Link to text 4
Not every table entry needs to be defined. A table element entry can have multiple entries. An entry consists of two values. A text and the link for the text.
The html-table is already defined. Now I want to fill it with the values (links) above.
My problem is, how to create an efficient data structure so that I easily can find table-positions that have entries (maybe without looping 10 rows 10 columns). For each entry I want to get the list of texts + links.
And how to access/read each entry of my definition. (I have no problem placing the value to my html-table.)
I'd really appreciate if someone could give me some code-example how to set up such a data structure.
var multiArray = [ ['element 0, 0', 'element 0, 1', 'element 0, 2'], ['element 1, 0', 'element 1, 1']];
and so on...
EDIT
every single notation in [] is an array, so you just have to combine them into an another array
Just use an array of array if the memory is not the problem;
var table = [];
table.length = 10; // 10 rows;
for (var i = 0; i < array.length; i++) {
table[i] = [];
table[i].length = 20; // 20 columns for each row.
}
If the table is big but only a few cells are used, you can also use a hash of hash:
var table = {};
table.rowCount = 10; // there're 10 rows
table[1] = {}
table[1].columnCount = 20 // 20 cells for row 1
table[1][3] = "hello world";
// visit all cells
for (var row in table) {
for (var column in table[row] {
console.log(table[row][column]);
}
}
You can even mix hash and array.
You could create a simple wrapper to make calling convenient: http://jsfiddle.net/QRRXG/2/.
A multidimensional array is just an array in another. So you can build an array with 10 arrays which in turn have 10 arrays in each. Then get one with arr[i][j].
Items can be represented as an object:
{ name: "foo", link: "bar" }
then such an item can be parsed like obj.name and obj.link.
var multi = (function() {
var data = [];
// initialize
for(var i = 0; i < 10; i++) {
data[i] = [];
for(var j = 0; j < 10; j++) {
data[i][j] = [];
}
}
return {
get: function(i, j) { // will return an array of items
return data[i][j];
},
push: function(i, j, v) { // will add an item
data[i][j].push(v);
},
clear: function(i, j) { // will remove all items
data[i][j] = [];
},
iterateDefined: function(f) {
for(var i = 0; i < 10; i++) {
for(var j = 0; j < 10; j++) {
if(data[i][j].length > 0) {
f(data[i][j], i, j);
}
}
}
}
};
})();
You can the use it like:
multi.push(2, 3, { name: "foo", link: "test1" });
multi.push(2, 3, { name: "bar", link: "test2" });
multi.push(1, 4, { name: "haz", link: "test3" });
multi.push(5, 7, { name: "baz", link: "test4" });
multi.clear(5, 7);
console.log(multi.get(2, 3)); // logs an array of 2 items
console.log(multi.get(1, 4)); // logs an array of 1 item
console.log(multi.get(5, 7)); // logs an array of 0 items
console.log(multi.get(2, 3)[0].name); // logs "foo"
console.log(multi.get(2, 3)[1].link); // logs "test2"
multi.iterateDefined(function(items, i, j) {
console.log(items, i, j); // will log two times
});
Create a utility Object:
var DataTable = {
source: [],
setEntry: function(i,j,e) {
var o ;
if( !!! ( o = this.source[i] ) ) o = this.source[i] = [] ;
o[j] = e ;
return this ;
},
getEntry: function(i,j) {
var o, e = null ;
if( !! ( o = this.source[i] ) ) e = o[j] || null ;
return e ;
}
} ;
The other answers seem to suggest placing dummy Arrays as placeholders for coordinates that are unused. This -- while it is not wrong -- is unnecessary: if you set an entry on an Array in JavaScript whose index exceeds the current range the Array is essentially padded with undefined values.
var a = [ ] ; // a length is 0
a[1024] = 1 // a length is now 1025, a[1] is undefined
Then add the values you require:
DataTable.setEntry( 1, 1, ["My text 1","Link to text 1","My text 2","Link to text 2"] )
.setEntry( 4, 5, ["My text 3","Link to text 3"] )
//..
;
The following control statements will return the value of the Arrays of the coordinates or null (if DataTable.source does not contain a nested Array for the given coordinates):
console.log("(!!) d.source: " + DataTable.getEntry(4,5) ) ;
console.log("(!!) d.source: " + DataTable.getEntry(1,1) ) ;
console.log("(!!) d.source: " + DataTable.getEntry(0,0) ) ;
Try it here:
link to JSFiddle
UPDATE:
This is a pretty old post, but since I received a comment to explain the snippet, here's an update with class syntax and a few more comments:
class DataTable {
data = [];
constructor() {
// bind methods to this instance
this.setEntry = this.setEntry.bind(this);
this.getEntry = this.getEntry.bind(this);
}
// set an entry at the given coordinates (row and column index pair)
setEntry(rowIndex, columnIndex, value) {
let row = this.data[rowIndex];
// create the row lazily if it does not exist yet
if(typeof row === 'undefined') {
this.data[rowIndex] = [];
row = this.data[rowIndex];
}
// set the value
row[columnIndex] = value;
}
// get the entry at the given coordinates (row and column index pair)
getEntry(rowIndex, columnIndex) {
const row = this.data[rowIndex];
// test if the row is defined; if not return null.
if(typeof row === 'undefined') { return null; }
else {
// return the value or fall back to null
return row[columnIndex] || null;
}
}
}
const d = new DataTable();
d.setEntry(1, 1, ["My text 1","Link to text 1","My text 2","Link to text 2"]);
d.setEntry(4, 5, ["My text 3","Link to text 3"]);
console.log(`d.getEntry(4, 5) = ${d.getEntry(4, 5)}`);
console.log(`d.getEntry(1, 1) = ${d.getEntry(1, 1)}`);
console.log(`d.getEntry(0, 0) = ${d.getEntry(0, 0)}`);
in JQuery i m having an array like
(1,2,6,8)
I have already selected the first element that is 1 which i have saved in a JQuery variable
submitterid = 1
On clicking a link I am trying to get the next greatest element in the Array than what I have selected in the submitterid..
How can I achieve this?
Edit:
How to find the last element in this array in the code
var previousId;
$("#previous").click(function (){
index = submitters.indexOf(submitterid),
nextId;
if (index - 1 < submitters.length) {
previousId = submitters[index-1];
} else {
// no ID index
// if i am having an array of 1,2,6,8 after moving to 1 from 8 to 6 - 2-1 i am trying to move to the last element of the array
}
alert(previousId);
});// previousId
Why couldn't you do something like:
var arr = [3, 5, 8, 3].sort(function (a, b) { return a - b; } );
var val = arr.pop();
Any keep popping the array -- saying that the values don't need to stay in the array.
If you are randomly picking values and you need the next highest, then write the appropriate sorting function.
You want a counter:
function counter(arr) {
this.arr = arr;
this.index = 0;
}
counter.prototype.next = function() {
return this.arr[this.index++];
}
You instantiate it and use it like:
var nums = new counter([1,2,3,4,5]);
nums.next() ; => 1
nums.next() ; => 2
nums.next() ; => 3
Actually, there is no need to use any jquery-specific stuff for this, apart from the click event handling, just 'plain javascript' will do;
var myArray = [ 1, 2, 6, 8 ];
var submitterid = 1;
$(function() {
$('a#id').click(function(event) {
event.preventDefault();
var greater = -1;
// loop through array
for (var i in myArray)
// find numbers greater than the specified number
if (i > submitterid)
// find numbers closest to specified number
if (i < greater || greater < 0)
greater = i;
if (greater < 0) {
// no greater value found, do something
} else {
// next biggest value is in variable greater, do something with it
}
});
});
You have to loop through the array.
Try this untested code:
// Your test array.
var arrValues = [ "1", "2", "6", "8" ];
var low = 1;
var high = 2;
// Loop over each value in the array.
$.each( arrValues, function( intIndex, objValue ){
if (objValue > high)
hight = objValue;
if (objValue < high)
if (objValue > low)
low = objValue
});
return low;
If your array is already sorted (see sort method), try this:
var arr = [1,2,6,8],
submitterid = 1,
index = arr.indexOf(submitterid),
nextId;
if (index + 1 < arr.length) {
nextId = arr[index+1];
} else {
// no ID index
}