Java Script: Assignment operator not working for a matrix - javascript

I'm trying to populate a matrix that I declared with random variables, but for some explicable reason the random values aren't being assigned to the cells in the Matrix.
Here is the declaration of said matrix:
this.weights_ih= new Matrix(this.hidden_nodes,this.input_nodes);
Please Keep in mind that this declaration is is part of a constructor of a class as shown below:
class NeuralNetwork
{
constructor (input_nodes,hidden_nodes,output_nodes)
{
this.input_nodes=input_nodes;
this.output_nodes=output_nodes;
this.hidden_nodes=hidden_nodes;
this.weights_ih= new Matrix(this.hidden_nodes,this.input_nodes);
this.weights_ho= new Matrix(this.output_nodes,this.hidden_nodes);
this.weights_ih.randomize();
this.weights_ho.randomize();
this.bias_h= new Matrix(this.hidden_nodes,1);
this.bias_0= new Matrix(this.output_nodes,1);
this.bias_h.randomize();
this.bias_0.randomize();
this.learning_rate=0.1;
}
}
The randomize() function returns a value between 1 and -1 and the definition is given below:
randomize()
{
for(let i=0;i<this.rows;i++)
{
for(let j=0;j<this.cols;j++)
{
this.data[i][j]=Math.floor(Math.random()*2 -1);
}
}
}
I have made sure that the randomize() is working as I did console log the variable this.data[i][j]. Here is the screen shot of that:
Therefore I assumed that the randomize() was not to blame as it was generating random values as expected and the data was being assigned to this.data[i][j].
But when I tabled the matrix this.weights_ih. This was the output I received:
I really do not understand why all the cells are undefined as in the randomize()values were being assigned to the variable this.data[i][j].
Do let me know if I've made an error.
Here's the Matrix class definition if that in any way might help you:
class Matrix
{
constructor (rows,cols)
{
this.rows=rows;
this.cols=cols;
this.data=[];
for(let i=0;i<this.rows;i++)
{
this.data[i]=[];
for(let j=0;j<this.cols;j++)
{
let temp=this.data[i];
temp[j]=0;
//this.data[i][j]=0;
}
}
}
static transpose(matrix)
{
let result = new Matrix(matrix.cols,matrix.rows)
for (let i=0;i<matrix.rows;i++)
{
for(let j=0;j<matrix.cols;j++)
{
result.data[j][i]=matrix.data[i][j];
}
}
return result;
}
toArray()
{
let arr=[];
for(let i=0;i<this.rows;i++)
{
for(let j=0;j<this.cols;j++)
{
arr.push(this.data[i][j]);
}
}
return arr;
}
static fromArray(arr)
{
let m= new Matrix(arr.length,1);
let v= arr.length;
for(let i=0;i<v;i++)
{
m.data[i][0]=arr[i];
}
return m;
}
randomize()
{
console.log("Rows:"+this.rows+"cols"+this.cols);
for(let i=0;i<this.rows;i++)
{
for(let j=0;j<this.cols;j++)
{
this.data[i][j]=Math.floor(Math.random()*2 -1);
}
}
}
static subtract(a,b)
{
let result= new Matrix(a.rows,a.cols);
for( let i=0;i<result.rows;i++)
{
for(let j=0;j<result.cols;j++)
{
result.data[i][j]=a.data[i][j]-b.data[i][j];
}
}
return result;
}
add(n)
{
if(n instanceof Matrix)
{
for( let i=0;i<this.rows;i++)
{
for(let j=0;j<this.cols;j++)
{
this.data[i][j]+=n.data[i][j];
}
}
}
else
{
for( let i=0;i<this.rows;i++)
{
for(let j=0;j<this.cols;j++)
{
this.data[i][j]+=n;
}
}
}
}
static multiply(a,b)
{
if(a.cols!==b.rows)
{
console.log("Error 001");
return undefined;
}
let result = new Matrix(a.rows,b.cols);
let sum=0;
for(let i=0;i<result.rows;i++)
{
for(let j=0;j<result.cols;j++)
{
sum=0;
for(let k=0;k<a.cols;k++)
{
sum+=a.data[i][k]*b.data[k][j];
}
result.data[i][j]=sum;
}
}
return result;
}
multiply(n)
{
for( let i=0;i<this.rows;i++)
{
for(let j=0;j<this.cols;j++)
{
this.data[i][j]*=n;
}
}
}
map(func)
{
//Apply a fucntion to every element
for( let i=0;i<this.rows;i++)
{
for(let j=0;j<this.cols;j++)
{
let val = this.data[i][j];
this.data[i][j]=func(val);
}
}
}
static map(matrix,func)
{
let result= new Matrix(matrix.rows, matrix.cols);
for(let i=0;i<matrix.rows;i++)
{
for(let j=0;j<matrix.cols;j++)
{
let val= matrix.data[i][j];
result.data[i][j]=func(val);
}
}
return result;
}
print()
{
console.table(this.data);
}
}
NeuralNetwork Declaration:
function setup()
{
let nn= new NeuralNetwork(2,2,2);
let input=[1,0];
let targets=[1,1];
nn.train(input,targets);
}
Thanks In Advance!

Related

Array.find to update a value in a nested array

I created a basket in JavaScript, it works perfectly except for one thing:
When we add products to the basket, we select a quantity and everything goes well, but if we click again to add the same product, instead of modifying the quantity of the product, the same product is added to the localStorage.
To avoid this problem, I have to search for the product in the localStorage with the Array.find() method, if the product exists, I modify the quantity, otherwise I add it. But I don't know how to do it the right way yet
let basket = JSON.parse(localStorage.getItem('monPanier')) || [];
let wishlist = JSON.parse(localStorage.getItem('myWishList')) || [];
let totalBasket = 0;
let nbrArticles;
let nbrWishlist;
function addBasket()
{
let quantity_cart = $(".input_quantity"+$(this).data("id")).val();
let name_article_cart = $(this).data("name");
let idArticle = parseInt(this.id.replace("add_basket_btn_",""));
let price_cart = $(this).data("price");
let total_price_cart = (quantity_cart * price_cart);
let newBasket = [idArticle,quantity_cart,name_article_cart,price_cart,total_price_cart];
basket.push(newBasket);
saveStorageBasket();
loadStorageBasket();
showBasket();
calculeNbrArticle();
console.log(newBasket);
}
function addWishlist()
{
let name_article_wishlist = $(this).data("name");
let idArticle = parseInt(this.id.replace("add_wishlist_btn_",""));
let price_article_wishlist = $(this).data("price");
let newWishlist = [idArticle,name_article_wishlist,price_article_wishlist];
wishlist.push(newWishlist);
saveStorageWishlist();
loadStorageWishlist();
showWishList();
calculeNbrWishlist();
}
function showBasket() {
//vider le panier
$("#basket").empty();
totalBasket = 0;
for(let i=0; i < basket.length; i++)
{
totalBasket = totalBasket + basket[i][4];
$("#basket").append("<tr><td>"+basket[i][1]+"</td>"
+"<td>"+basket[i][2]+"</td>"
+"<td>"+basket[i][3]+"€</td>"
+"<td>"+basket[i][4]+"€</td>"
+"<td><button data-id='"+i+"' class='btn_cancel_basket'>supprimer</button></td>"
+"</tr>");
}
// installer un event
$("#basket button.btn_cancel_basket").on("click",suppArticleBasket);
$("#totalBasket").text(totalBasket+" €");
}
function suppArticleBasket()
{
let index = $(this).data('id');
console.log(index);
basket.splice(index,1);
saveStorageBasket();
loadStorageBasket();
showBasket();
}
function showWishList()
{
for(let i=0; i < wishlist.length; i++)
{
$("#Wishlist").append("<tr><td>"+wishlist[i][1]+"</td>"
+"<td>"+wishlist[i][2]+"</td>"
+"</tr>");
}
}
function emptyBasket()
{
if(basket == null || basket == 0)
{
console.log("panier = true");
return true;
}else
{
console.log("panier = false");
return false;
}
}
function validateBasket()
{
if(emptyBasket() == false)
{
loadStorageBasket();
basket = JSON.stringify(basket); //js --> json
console.log($.get("index.php","action=appelAjax2&Basket="+basket+"&total="+totalBasket,resetBasket));
}
}
function resetBasket(reponse){
$("#confirmationcmd").html("<p>Commande validée.</p>");
$("#basket").empty();
basket.length = 0;
localStorage.clear();
loadStorageBasket();
showBasket();
totalBasket = 0;
calculeNbrArticle();
}
function resetBasket2(reponse){
$("#confirmationcmd").html("<p>Panier annulé.</p>");
$("#basket").empty();
basket.length = 0;
localStorage.clear();
loadStorageBasket();
showBasket();
totalBasket = 0;
calculeNbrArticle();
}
function resetWishlist(reponse){
$("#confirmationWishlist").html("<p>Wishlist remise à zéro.</p>");
$("#wishlist").empty();
wishlist.length = 0;
localStorage.clear();
loadStorageWishlist();
showWishList();
totalWishlist = 0;
calculeNbrWishlist();
}
function saveStorageWishlist(){
localStorage.setItem("myWishList", JSON.stringify(wishlist));
}
function loadStorageWishlist(){
wishlist = localStorage.getItem("myWishList");
if(wishlist == null)
{
wishlist =[];
}
else
{
wishlist = JSON.parse(wishlist);
}
}
function calculeNbrWishlist()
{
loadStorageWishlist();
nbrWishlist = wishlist.length;
$("#nbrWishlist").text("("+nbrWishlist+")");
}
function saveStorageBasket(){
localStorage.setItem("monPanier", JSON.stringify(basket));
}
function loadStorageBasket(){
basket = localStorage.getItem("monPanier");
if(basket == null)
{
basket =[];
}
else
{
basket = JSON.parse(basket);
}
}
function calculeNbrArticle()
{
loadStorageBasket();
nbrArticles = basket.length;
$("#nbrArticles").text("("+nbrArticles+")");
}
$(function()
{
calculeNbrArticle();
calculeNbrWishlist();
loadStorageBasket();
loadStorageWishlist();
showBasket();
showWishList();
$(".add_basket_btn").on('click',addBasket);
$(".btn_wishlist").on('click',addWishlist);
$("#validateButton").on('click',validateBasket);
$("#resetButton").on('click',resetBasket2);
$("#resetButtonWishlist").on('click',resetWishlist);
});
The basic idea:
push the new basket array if empty
check if the ID is already in the basket array
if so, update the quantity
if not, add the new basket
I have read the following learning resources about:
for loops (w3schools)
find (MDN)
filter (MDN)
According to what I have read in this post Array.find does not work because it finds only the first element. I used the suggested filter option.
The essential part with changes:
function updateQuantity(basket, newBasket, idArticle)
{
// filter: search for articleId in array of arrays
if (basket.filter(({ 1: n }) => n === idArticle)) {
for(i = 0; i < basket.length; i++) {
basket[i][1] += 1;
}
} else {
basket.push(newBasket)
}
}
function addBasket()
{
let quantity_cart = 1
let name_article_cart = "productName"
let idArticle = 1
let price_cart = 10
let total_price_cart = (quantity_cart * price_cart);
let newBasket = [idArticle,quantity_cart,name_article_cart,price_cart,total_price_cart];
if (basket.length === 0) {
basket.push(newBasket)
}
else
{
updateQuantity(basket, newBasket, idArticle)
}
console.log(basket)
}
My complete test code:
let basket = JSON.parse(localStorage.getItem('monPanier')) || [];
let totalBasket = 0;
let nbrArticles;
function updateQuantity(basket, newBasket, idArticle)
{
// filter: search for articleId in array of arrays
if (basket.filter(({ 1: n }) => n === idArticle)) {
for(i = 0; i < basket.length; i++) {
basket[i][1] += 1;
}
} else {
basket.push(newBasket)
}
}
function addBasket()
{
let quantity_cart = 1
let name_article_cart = "productName"
let idArticle = 1
let price_cart = 10
let total_price_cart = (quantity_cart * price_cart);
let newBasket = [idArticle,quantity_cart,name_article_cart,price_cart,total_price_cart];
if (basket.length === 0) {
basket.push(newBasket)
}
else
{
updateQuantity(basket, newBasket, idArticle)
}
console.log(basket)
}
function suppArticleBasket()
{
let index = 1
console.log(index);
basket.splice(index,1);
saveStorageBasket();
loadStorageBasket();
}
function emptyBasket()
{
if(basket == null || basket == 0)
{
return true;
} else
{
return false;
}
}
function saveStorageBasket(){
localStorage.setItem("monPanier", JSON.stringify(basket));
}
function loadStorageBasket(){
basket = localStorage.getItem("monPanier");
if(basket == null)
{
basket =[];
}
else
{
basket = JSON.parse(basket);
}
}
$(function()
{
loadStorageBasket();
$("#add_basket_btn").on('click',addBasket);
});
<button id="add_basket_btn">Add</button>

How would I change this code to a different format? (Javascript)

The code below is the code that I have written:
function singer(artist) {
var songs = [];
for(var i = 0; i < music.length;i++ ){
if(music[i].artist.indexOf(artist) > -1) {
songs.push(music[i].name);
}
}
return songs;
}
The code that I want to look similar to the function singer(artist) code is this:
const genreCount = () => {
const genres = music.reduce((result, cur) => {
cur.genres.forEach(g => {
if (result.hasOwnProperty(g)) {
result[g] += 1;
}
else
result[g] = 1;
});
return result;
}, {});
return genres;
}
I am unfamiliar with this type of format in Javascript, how would I change it so that const genreCount will look like function singer(artist).
This is what you will get if you want to change that function:
function genreCount() {
const genres = music.reduce(function(result, cur) {
cur.genres.forEach(function(g) {
if (result.hasOwnProperty(g)) {
result[g] += 1;
}
else
result[g] = 1;
});
return result;
}, {});
return genres;
}
or (if you want to assign that fucntion to a const anyway):
const genreCount = function() {
const genres = music.reduce(function(result, cur) {
cur.genres.forEach(function(g) {
if (result.hasOwnProperty(g)) {
result[g] += 1;
}
else
result[g] = 1;
});
return result;
}, {});
return genres;
}
You just should replace arrow functins with the regular function expressions. But I don't know why do you need that.
this style is called functional programming
const singer = artist => music.filter(m => artist.indexOf(m.artist) > -1).map(m => m.name)
here is a good interactive tutorial if you are interested
Functional Programming in Javascript
UPDATE:
oops, sorry for misunderstanding your questions
here is genreCount rewritten with for-loop:
function genreCount(){
const genres = {};
for(var i=0; i<music.length; i++){
var g = music[i]
if (genres.hasOwnProperty(g)) {
genres[g] += 1;
}
else{
genres[g] = 1;
}
}
return genres;
}

Accessing 'this' inside JS iterator's next() method? [duplicate]

This question already has an answer here:
Is there a way to have lexical `this` in methods using the ES6 shorthand method notation?
(1 answer)
Closed 4 years ago.
I'm currently working on a Eloquent JavaScript's object assignments and I'm wondering if there is any way that I can use this inside iterator's next() method (see the code)
class Group {
constructor() {
this.members = [];
}
add(member) {
if (this.has(member)) return;
this.members.push(member);
}
delete(member) {
if (!this.has(member)) return;
this.members.splice(this.members.indexOf(member), 1);
}
has(member) {
return this.members.indexOf(member) !== -1
}
static from(iterable) {
const group = new Group();
for (const element of iterable) {
group.add(element);
}
return group;
}
[Symbol.iterator]() {
let current = 0;
let last = this.members.length - 1;
const that = this;
return {
next() {
if (current <= last) {
return {
done: false,
value: that.members[current++]
}
} else return { done:true }
}
}
}
}
for (let value of Group.from(["a", "b", "c"])) {
console.log(value);
}
As you can see there I'm using this weird const that = this pattern. Is there any way I can get rid of it? Besides using arrow function and extracting iterator to a separate class, as suggested in the solution.
The sortest way, could be an implementation of a default iterator of the object in the constructor section and use yield* expression for delegating to another generator of the array this.members.
constructor() {
this.members = [];
this[Symbol.iterator] = function* () {
yield* this.members;
}
}
class Group {
constructor() {
this.members = [];
this[Symbol.iterator] = function* () {
yield* this.members;
}
}
add(member) {
if (this.has(member)) return;
this.members.push(member);
}
delete(member) {
if (!this.has(member)) return;
this.members.splice(this.members.indexOf(member), 1);
}
has(member) {
return this.members.indexOf(member) !== -1
}
static from(iterable) {
const group = new Group();
for (const element of iterable) {
group.add(element);
}
return group;
}
}
for (let value of Group.from(["a", "b", "c"])) {
console.log(value);
}
.as-console-wrapper { max-height: 100% !important; top: 0; }
you can use the arrow function
class Group {
constructor() {
this.members = [];
}
add(member) {
if (this.has(member)) return;
this.members.push(member);
}
delete(member) {
if (!this.has(member)) return;
this.members.splice(this.members.indexOf(member), 1);
}
has(member) {
return this.members.indexOf(member) !== -1
}
static from(iterable) {
const group = new Group();
for (const element of iterable) {
group.add(element);
}
return group;
}
[Symbol.iterator]() {
let current = 0;
let last = this.members.length - 1;
return {
next: () => {
if (current <= last) {
return {
done: false,
value: this.members[current++]
}
} else return { done:true }
}
}
}
}
for (let value of Group.from(["a", "b", "c"])) {
console.log(value);
}

Get index of array is not working

I am learning Vue and I am trying to access a string in an array by it's index, but I always get an error when trying to read the string. Here's my code:
var vm = new Vue({
el: '#top',
data: {
Cars: [],
DefaultCarList: [],
AddedCars: [],
SelectedCar: ''
},
methods: {
addCar: function(car) {
var addedCarCount = this.AddedCars.length;
var defaultCarCount = this.DefaultCarList.length;
var containsCar = function () {
for (var i = 0; i < addedCarCount; i++)
{
if (this.AddedCars[i] === car) // error here
{
return true;
}
}
return false;
}
var carIsValid = function() {
for(var i = 0; i < defaultCarCount; i++)
{
if(this.DefaultCarList[i] === this.SelectedCar) // error here
{
return true;
}
}
return false;
}
if (containsCar() === false && carIsValid){
this.AddedCars.push(car);
}
}
}
})
HTML:
<label for="carsId">Cars</label>
<select id="carsId" name="cars" v-model="SelectedCar">
<option disabled value="">Select</option>
<option v-for="car in DefaultCarList" :value="flavor">{{car}}</option>
</select>
<div>
<button type="button" class="hollow button success small"
v-on:click="addCar(SelectedCar)">Add Flavor</button>
</div>
Is it valid to iterate over an array like this in Vue and access the property by it's index? What is the correct way to do this?
Problem is with 'this' keyword it uses inner this where it doesn't have DefaultCarList variable, should use () => {} syntax .Error in this code
var carIsValid = function() {
for(var i = 0; i < defaultCarCount; i++)
{
if(this.DefaultCarList[i] === this.SelectedCar) // error here
{
return true;
}
}
return false;
}
should be
var carIsValid = () => {
for(var i = 0; i < defaultCarCount; i++)
{
if(this.DefaultCarList[i] === this.SelectedCar) // error here
{
return true;
}
}
return false;
}
and
var containsCar = () => {
for (var i = 0; i < addedCarCount; i++)
{
if (this.AddedCars[i] === car) // error here
{
return true;
}
}
return false;
}
The problem is that this it's not a reference to your model.
In your example this is a reference to window object.
Have a look here in order to understand the scope of this keyword in javascript.
You should use arrow functions.
var containsCar = () => {
for (var i = 0; i < addedCarCount; i++)
{
if (this.AddedCars[i] === car) // error here
{
return true;
}
}
return false;
}
or you could just define a self variable.
var self=this;
var containsCar = function() {
for (var i = 0; i < addedCarCount; i++)
{
if (self.AddedCars[i] === car) // error here
{
return true;
}
}
return false;
}
Further more, I recommand you to use native javascript functions in order to have a clean code.
var containsCar = function () {
for (var i = 0; i < addedCarCount; i++)
{
if (this.AddedCars[i] === car) // error here
{
return true;
}
}
return false;
}
var carIsValid = function() {
for(var i = 0; i < defaultCarCount; i++)
{
if(this.DefaultCarList[i] === this.SelectedCar) // error here
{
return true;
}
}
return false;
}
can be achieved using some method :
The some() method tests whether at-least one element in the array
passes the test implemented by the provided function.
var containsCar = () => {
return this.AddedCars.some(a=>a==car);
}
var carIsValid = () => {
return this.DefaultCarList.some(a=>a === this.SelectedCar);
}

Dyanamic Execution of javascript code

I have the following JavaScript:
var djs = function (ob) {
return {
remove: function () { //removes element
if (is_array(ob)) {
for (var i = 0; i < ob.length; i++)
ob[i].parentNode.removeChild(ob[i]);
} else {
ob.parentNode.removeChild(ob);
}
},
empty: function () { //makes element empty
if (is_array(ob)) {
for (var i = 0; i < ob.length; i++)
ob[i].innerHTML = "";
} else {
ob.innerHTML = ""
}
},
html: function (str) { //gets or sets innerHTML
if (str) {
if (is_array(ob)) {
for (var i = 0; i < ob.length; i++)
ob[i].innerHTML = str;
} else {
ob.innerHTML = str;
}
} else {
if (is_array(ob)) {
for (var i = 0; i < ob.length; i++)
rob += ob[i].innerHTML;
return rob;
} else {
return ob.innerHTML;
}
}
}
}
}
Here every time I am checking whether ob is an array or not and executing code. I want to minimize this, like instead of:
if (is_array(ob)) {
for (var i = 0; i < ob.length; i++)
ob[i].parentNode.removeChild(ob[i]);
} else {
ob.parentNode.removeChild(ob);
}
I want to use a function like, doEval(ob,code,return), in this case,
doEval(ob,"parentNode.removeChild("+ob+")",NULL);
"return" parameter will return if I specify any like innerHTML. Can any one help?
Don't repeat is_array check:
var djs=function(ob) {
if (!is_array(ob)) ob = [ob];
#SHiNKiROU is right of course, but just to provide an example of how to solve your problem with higher-order functions:
function doToAll(ob, callback) {
if(is_array(ob)) {
for (var i = 0; i < ob.length; i++) {
callback(ob[i]);
}
} else {
callback(ob);
}
}
...
remove:function(){ //removes element
doToAll(ob, function(actualOb) { actualOb.parentNode.removeChild(actualOb); });
},
...
But again, use #SHiNKiROU:s answer for this particular case.
Try this:
function doEval(a, b, c) {
if(is_array(a)) {
eval(b);
} else {
eval(c);
}
}
NULL doesn't exist by the way, it is null.

Categories