I am trying to make a for loop such that the value 0 will change to 1 if either of the first two values matches the previous row in the array.
So for example, row 2 and row 3 will have the 0 value change to 1, because row 1 has the values of 1 and 3, which matches one of the two values in row 2 and 3.
Following such a case, all the value 0 will all change to 1 eventually (since row 4 will have values of row 2 and 3).
How can I create such a loop?
edgeArray=[[1,3,0],
[1,4,0],
[2,3,0],
[2,4,0]]
for(var counter = 1; counter =< edgeArray.length; counter ++ {
if current edgeArray[i][j][0] && previous edgeArray[i][j][0] on same row && edgeArray[i][j][0] ==
then edgeArray[i][j][0] = edgeArray[i][j][1]
The end result to be
edgeArray=[[1,3,0],
[1,4,1],
[2,3,1],
[2,4,1]]
Not sure I understand fully, but is this what you want??
for(var i = 1; i <= edgeArray.length; i ++) {
// for each row (from second row onwards)
if ( edgeArray[i][0] == edgeArray[i-1][0]
// is the first val the same as prev row?
|| edgeArray[i][1] == edgeArray[i-1][1]
// or second val same as prev row?
|| edgeArray[i-1][2] == 1) {
// or is there already a '1' in 3rd col of prev row?
edgeArray[i][2] = 1;
// in that case change 3rd column to '1'
}
}
If you don't want to 'carry over' the previous 1s to future rows, and you just want the 3rd column to reflect only the previous two rows, then just get rid of the third disjunctive condition in the if statement.
Not sure I understand your requirement, but this results the way you want:
var edgeArray = [[1,3,0],
[1,4,0],
[2,3,0],
[2,4,0]];
var temp = [[],[]];
for(var i=0; i<edgeArray.length; i++){
for(var j=0; j<2; j++){
var found = temp[j].indexOf(edgeArray[i][j]);
if(found > -1){
edgeArray[i][2] = 1;
}else{
temp[j].push(edgeArray[i][j]);
}
}
console.log(edgeArray[i].toString())
}
Related
I'm practicing some programming logic with a challenge that a friend shared with me. Here's the problem:
Write a script that takes an integer n as the numbers of rows and columns of a matrix and take the element list of the matrix.
Example: n=3
matrix = [[11 2 4],
[4 5 6],
[10 8 -12] ]
And print the determinant of the matrix to -100 <= m[i][j] <= 100
My solution, code, problem, question so far:
SOLUTION
Create an array with n empty positions, in the future those positions will store other arrays, they will be each line of the matrix.
Loop through each empty position to fill with a new matrixLine
Create a variable inside the loop that will be a matrix line with elements
Loop the element list to get the necessary elements of a line
Put the matrix line with elements on the final matrix
CODE
function createMatrix(rowsAndColumns, elementsList) {
const finalMatrix = Array(rowsAndColumns)
for(let i = 0; i < finalMatrix.length; i++) {
let matrixLineWithElements = []
for(let k = 0; k < rowsAndColumns; k++) {
matrixLineWithElements[k] = elementsList[k]
}
finalMatrix[i] = matrixLineWithElements
}
}
PROBLEM
As you have probably noticed on the code, I'm taking the same elements from the list to form a line. The final matrix is formed successfully, but I can't figure out how to cout different values per line, here's an image of my terminal:
QUESTIONS
I stopped trying to figure out while code and took the following notes -
If I have a list of four elements:
[10. 90, 100, 25]
I will form a matrix 2X2, so I need to count the elements of the list.
0(zero) and 2 are the start point of the counting, with a counting salt of 2 (same value of n variable).
There's some kind of pattern here, look, if I got a 9 element list, such as
[10, 90, 100, 25, 36, 48, 2, 5, 6]
I will form a matrix 3X3, so I need to count the elements of the list.
0(zero), 3 and 6 are the starting point of counting, with a counting salt of 3 (same value of n variable).
How can I do this counting programmatically?
Do my approach and thinking on the problem make some sense or there are better ways of doing it?
Let's go by examples
Col 0
Col 1
Row 0
0
1
Row 1
2
3
Col 0
Col 1
Col 2
Row 0
0
1
2
Row 1
3
4
5
Row 2
6
7
8
These are 2 "matrices" with cells that I filled with indexes of elementsList elements that are to be placed in them.
You can see that for the "0th" row the column number is the index, but for the 1st row it's the column index increased by the number of elements in the first row.
In the 2nd row it's the column index increased by 2 times the length of row (or by the number of elements already placed if we go with the second version of code - with counter).
We can deduce that nth row indexes start at n*(length of row) and increase by one just as the column indexes hence the formula for the elementsList index in the matrix cell: (row number) * (length of row) + columnn index
function createMatrix(rowsAndColumns, elementsList) {
const finalMatrix = Array(rowsAndColumns)
for(let i = 0; i < finalMatrix.length; i++) {
let matrixLineWithElements = []
for(let k = 0; k < rowsAndColumns; k++) {
matrixLineWithElements[k] = elementsList[k+i*finalMatrix.length] // here you just needed to add i times (max i)
}
finalMatrix[i] = matrixLineWithElements
}
return finalMatrix // I added this only so that it can be printed
}
console.log(createMatrix(2,[1,2,3,4]))
Other option:
function createMatrix(rowsAndColumns, elementsList) {
const finalMatrix = Array(rowsAndColumns)
let counter = 0 // Added counter
for(let i = 0; i < finalMatrix.length; i++) {
let matrixLineWithElements = []
for(let k = 0; k < rowsAndColumns; k++) {
matrixLineWithElements[k] = elementsList[counter]
counter+=1 // Increment counter
}
finalMatrix[i] = matrixLineWithElements
}
return finalMatrix // I added this only so that it can be printed
}
console.log(createMatrix(2,[1,2,3,4]))
However, I dislike mutating the variables
function createMatrix(n, elementsList) {
const range = (length) => [...Array(length).keys()]
const finalMatrix = range(n).map((i) =>
range(n).map((j) =>
elementsList[i * n + j]
))
return finalMatrix // I added this only so that it can be printed
}
console.log(createMatrix(2,[1,2,3,4]))
I have an JS Array that is supposed to show only one element. It does, however its index is 1 rather than 0 and the count is 2. Also the array does not show a 0 index.
My code:
var _UnitOfMeasureRelatedUnitData = [];
var rows = $('#jqxUOMRelatedUnitsDropdownGrid').jqxGrid('getrows');
var RecordCount = 0;
if (rows.length !== 1 && rows[0]["UOMRelatedUnit_Name"] !== ""){
for(var i = 0; i < rows.length; i++){
var row = rows[i];
var _row = {};
if(row.UOMRelatedUnit_AddItem !== F) {
RecordCount += 1;
_row["Name"] = $("#txtUnitOfMeasureSetName").val();
_row["Active"] = T;
_row["UnitOfMeasureTypeID"] = $("input[type='radio'][id='rblUnitOfMeasureType']:checked").val();
_row["BaseUnitID"] = $("input[type='radio'][id='rblUnitOfMeasureBaseUnit']:checked").val();
_row["RelatedUnitDisplayOrder"] = RecordCount;
_row["RelatedUnitName"] = row.UOMRelatedUnit_Name;
_row["RelatedUnitAbbreviation"] = row.UOMRelatedUnit_Abbreviation;
_row["RelatedUnitConversionRatio"] = row.UOMRelatedUnit_ConversionOfBaseUnits;
_row["UnitOfMeasureSetID"] = UnitOfMeasureSetID;
_UnitOfMeasureRelatedUnitData[i] = _row;
}
}
....
}
In my JQx Grid, I have at least four choices. For this issue, Ive only selected the 2 choice in the Grid and its AddItem value is True, everything else is False.
What do I need to change in my logic as I can not see it at this point?
EDIT 1
I overlooked the placement of RecordCount += 1;, I will try moving it to the end of the assignments and see what happens.
EDIT 2
The placement made no difference.
Maintain another variable for indexing your data like this
var index=0; // place this outside of for loop
_UnitOfMeasureRelatedUnitData[index++] = _row;
you don't need RecordCount += 1; .
you can get the rowscount by using _UnitOfMeasureRelatedUnitData.length
I'm trying to get a function to loop through data in two tables and put them into an object. The first for-loop that goes through the first table does this fine, but the second for-loop that goes through the second table spits out an empty object when there's only 1 row to go through.
However, when there is more than 1 row, then all of the objects have the values as the second row.
I really don't understand what I'm doing wrong here:
function foo(){
var rows = $('#table1').find('tr');
var array1 = [];
for(var i = 1; i < rows.length-1; i++){
var row = $(rows[i]).find('input');
var o = {
name : $(row[0]).val(),
bday : $(row[1]).val(),
parent : $(row[2]).val(),
parentBDay : $(row[3]).val(),
parentNumber : $(row[4]).val()
};
array1.push(o);
}
var array2 = [];
rows = $('#table2').find('tr');
for(var j = 1; j < rows.length-1; j++){
var row = $(rows[i]).find('input');
var o = {
name : $(row[0]).val(),
bday : $(row[1]).val(),
phoneNumber : $(row[2]).val()
};
console.log('wtf: ' + JSON.stringify(o));
array2.push(o);
}
}
Your problem is that your indexes in the for cycle are not looping well. You start the for cycle from 1, which, in case you want to use the very first element, then it is wrong. Note, that indexing begins from 0. If you miss the very first element on purpose, because it is a header row or something, then this is not a problem. However, the end sign, like
< rows.length - 1
is clearly wrong. Let's suppose, the number of rows is 50. Then its last index is 50 - 1 = 49. If you loop from one until you reach the number below 50 - 1, then your last index will be 48 and you will miss the very last element. Your condition should be either < rows.length or <= rows.length - 1.
I created a table in my HTML code. It has 9 columns and 13 rows. It gets filled up completely by a JavaScript loop that fills it with names of people from a few arrays. However, I want to add a validation step that makes sure that no two cells within a row hold the same value and that the value of a each cell does not repeat in the cell directly beneath it.
Since I am only able to access the values of the cells of the table as a NodeList, I decided to make it into an array to use the IndexOf property to search through the array:
var table1 = document.getElementsByTagName("td");
var table1Array = []; //number of "td" elements on page
for (i = 0; i < 117; i++) {
table1Array[i] = table1[i].innerHTML;
}
I don't know of a more elegant method (sort of a beginner here). So I set up some nested loops to compare each cell to each element in the row array I create (for all 13 rows):
function validateCells() {
for (i = 0; i < 117; i = i + 9) { //increment for going to next column (after 9 cells or elements in array)
for (j = 0; j < 8; j++) {
var curCell = table1Array[i];
var curRow = []; //I'm ignoring the first column which is "date", so it has 8 elements rather than 9
for (k = 0; k < 8; k++) {
curRow[k] = document.getElementById("row" + j).children[k].innerHTML;
}
if (curRow.indexOf(curCell) != -1) {
curCell = "CONFLICT"; //trying to change value in table. Doesn't work.
}
}
}
}
Unfortunately, this won't work. I don't even know if modifying the value of the curCell reference variable will actually change the value of the table1Array at that location, even less if it will change the data in the table.
Am I using the indexOf property correctly? Do I use the != comparison operator or !==? Does indexOf return the index as a Is there any other less complicated, more elegant to do this? I just started with jQuery, maybe it can help simplify the code and make it less error-prone.
Sorry for the all the questions, I'm really trying to understand how all of this works. Thanks!
You should get an array of rows, each row is an array of cells. That way the validation is much easier. I'm not sure about how you want to show the conflict. In this demo I've just highlight the duplicated cells (conflicted) in red (at least I like this kind of showing conflict rather than modifying the conflicted cells' text).
HTML:
<table>
<tr><td>1</td><td>2</td><td>3</td></tr>
<tr><td>1</td><td>5</td><td>6</td></tr>
<tr><td>7</td><td>8</td><td>7</td></tr>
<tr><td>8</td><td>9</td><td>10</td></tr>
</table>
<button>Check constraints</button>
CSS:
td {
width:100px;
height:50px;
border:1px solid black;
}
table {
border:1px solid black;
border-collapse:collapse;
}
td.invalid {
background:red;
}
JS:
$('td').attr('contenteditable',true);
var cell;
function highlight(){
$(arguments).toggleClass('invalid',true);
}
function checkConstraints(e){
//reset style before re-checking
$('td.invalid').toggleClass('invalid');
//get rows as an array of array
var rows = $('tr').map(function(elem,i){
return [$(this).children('td').toArray()];
}).toArray();
//loop through the rows
for(var i = 0; i < rows.length; i++){
cell = {};
for(var j = 0; j < rows[i].length; j++){
var cellText = $(rows[i][j]).text();
if(cell[cellText]) {
highlight(cell[cellText], rows[i][j]);
} else {
cell[cellText] = rows[i][j];
}
if(i < rows.length - 1 &&
cellText == $(rows[i+1][j]).text()){
highlight(rows[i][j],rows[i+1][j]);
}
}
}
}
$('button').click(checkConstraints);
Demo.
Note that, I set contenteditable for all the cells (td), you can edit the cells text to what you want and click the button to test the demo.
You can use the table rows and cells collections for the iteration. The following does a literal comparison of the text content, you may wish to process the text first to "normalise" it in regard to whitespace.
<table id="t0">
<tr><td>foo<td>bar<td>fum</td>
<tr><td>fum<td>bar<td>foo</td>
<tr><td>foo<td>fum<td>fum</td>
</table>
<script>
compareRows(document.getElementById('t0'));
function compareRows(table) {
var row, rows = table.rows;
var cell, cells;
var rowText;
// For each row in the table
for (var i=0, iLen=rows.length; i<iLen; i++) {
row = rows[i];
cells = row.cells;
// Compare the text in each cell
for (var j=0, jLen=cells.length; j<jLen; j++) {
cell = cells[j];
for (var k=0; k<jLen; k++)
if (k != j && cells[k].textContent == cell.textContent) {
// cell text is repeated in current row
console.log('row ' + i + ' cell ' + j + ' text repeated in cell ' + k);
}
// Compare with the text in the cell immediately below (if there is one)
if (i < iLen-2 && cell.textContent == rows[i+1].cells[j].textContent) {
// cell text is repeated in next row
console.log('row ' + i + ' cell ' + j + ' text repeated in row ' + (i+1));
}
}
}
}
</script>
Note that repeated text in a row will be reported twice.
The above uses the textContent property, which may be supported as innerText in some user agents. It also runs about 10 times faster than the jQuery alternative.
I have a javascript issue. Suppose I have an input box that the user can enter the values and I store them in an array and display the array. Values like:
apple 8, orange 4, pear 10, orange 3.
What I want to do is to show the latest updated added value so when the user wants to see the values they see which is (all values in the array plus the latest updated value) so I dont want to show orange 4! I want to show orange 3 instead.
apple 8, pear 10, orange 3. //numbers are quantity of fruits that I randomly set
So the orange with the quantity of 4 is replaced y the orange with quantity of 3. This is my code for creating array, I think I should use key value store or hash instead, to display the last updated value, can you give me any hint? Thanks
this.fruitArray.push(inputData);
this.fruitArray = this.removeDuplicate(this.fruitArray);
if(inputData !== "" ){
$('#displayBox').html(this.fruitArray);
}
removeDuplicate: function(Arr){
var cur, found;
for (i = Arr.length - 1; i >= 0; i--) {
cur = Arr[i];
found = false;
for (j = i - 1; !found && j >= 0; j--) {
if (cur === Arr[j]) {
if (i !== j) {
Arr.splice(i, 1);
}
found = true;
}
}
}
return Arr;
},
if you just want access to the last element of an array, you can do it like this:
var lastElement = myArray[myArray.length-1]
in your case:
$('#displayBox').html(fruitArray[fruitArray.length -1]);
example: FIDDLE
--EDIT---------------------------
Still not sure of what you try to achieve, but could you just store the last fruit update in an other variable ?
var fruitArray = [];
var lastFruitUpdate = "";
....
if(inputData !== "" ){
lastFruitUpdate = inputData;
if(fruitArray[inputData] != undefined){
fruitArray[inputData]++;
}else{
fruitArray[inputData] = 1;
}
$('#displayBox').html(lastFruitUpdate+"( "+fruitArray[lastFruitUpdate]+")");
}
example: FIDDLE
If you want last element of array which is just added into array, then use below statement.
this.fruitArray.push[this.fruitArray.length-1]