Working with array of objects in JavaScript - javascript

Question: Develop an array of 1000 objects (having properties name and number as shown).
We need a function to convert every object so the name is uppercased
and values are 5 times the original and store into the higher
variable. Similarly, another function that converts every object so
the name is lower case and value is 3 times the original, store this
into the little variable.
We need a function that takes each object in higher and finds all
objects in little that evenly divide into it. Example: 30 in
higher object is evenly divided by 6 in little.
The output of 2 must be an array of higher numbers, and in every
object there should be got (which is a variable inside the object) which will contain every little
object that evenly divided the higher.
My code:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<script>
var n = 1000;
var sample = [];
for (var i = 0; i < n; i++) sample.push({
name:'John' + i,
value: i
});
console.log(sample);
function Converter() {
var n = 1000;
var higher = sample;
for (var i = 0; i < n; i++) higher.name = 'John' + i;
higher.value = i * 5;
console.log(higher);
}
</script>
</body>
</html>
The array of objects is created and it is as expected/required by the question, however, the converter function for higher does not work, also how should the 3rd question be done?

Some thoughts:
1) only constructors should start with a capital letter, functions should be camelcase by convention so it should be converter
2) you don't call converter() so it never gets executed
3) make sure to indent your code properly var n and var sample should be at the same depth.
4) if you omit the brackets after an if or for, only the following statement gets inside the branch, so in your case you do:
for (var i = 0; i < n; i++)
higher.name = 'John'+i;
higher.value = i*5;
so the second line isn't even executed in the loop, you want:
for (var i = 0; i < n; i++) {
higher.name = 'John'+i;
higher.value = i*5;
}
5) higher.name makes little sense as higher is an array, you want to change the name of the ith higher number which you can do with higher[i].name
6) "John1" is not in caps, you want to call toUpperCase on it (("John1").toUpperCase())
also how should the 3rd question be done?
I guess fixing your code and doing the second question is enough for today.
You could continue reading:
Coding style matters
js array iterations

You should also try to think in a more structured manner about your code here. I would suggest writing separate functions for each problem and giving them meaningful names. Perhaps something like the following:
var n = 1000;
var sample = [];
for (var i = 0; i < n; i++) sample.push({
name: 'John' + i,
value: i
});
console.log(sample);
var higher = convertToHigher(sample);
var little = convertToLittle(sample);
var higherWithDivisors = findAllDivisors(higher, little);
function convertToHigher(arr) {
var newArr = [];
// TODO: iterate through each entry in arr, create a new modified object
// with a higher value and add it to newArr
return newArr;
}
function convertToLittle(arr) {
var newArr = [];
// TODO: iterate through each entry in arr, create a new modified object
// with a lower value and add it to newArr
return newArr;
}
function findAllDivisors(arr1, arr2) {
var newArr = [];
// TODO: solve problem 3 here
return newArr;
}

Related

Maximum calls exceeded somehow

Today I (tried) created some code to create mcq questions.
The code is supposed to generate a random codon, find its amino acid from the codon table/chart and display it on the document along with other (3) random wrong options.
I want to make a mcq with 4 options (1 is correct rest are wrong).
What I am trying to do below is: The computer will form a random sequence of 3 nucleotides (i.e.digits) using form() function. Variable formed will store a codon (eg. UCA, ACC etc.) which will be the question.
Now I declared array arr which will store the correct answer at 0th position.
Then I created a function generateWrongOptions() which will (is supposed to) add the other 3 dissimilar wrong answers to the array. What I tried to do here is that the function will declare a new amino acid (eg. Phe, Ile, Met etc.) which is stored as wrong and a new empty array arr2. The next loop is supposed to check if wrong is already present in arr or not; if it is not then it will push an element 'a' ('a' here doesn't has any meaning) in arr2, if it is then it won't. Now if will check if the arr length is equal to arr2 which simply means if the variable wrong is unique or not (or is duplicate).
I wanted to create 4 options (1 was already present) hence I looped the code for i<3 times.
I found better ways to do this same task online, but those were more advanced and I couldn't understand them. Hence I'd come with my own solution (best I could've guessed).
const obj = {
UUU:"Phe",
UUC:"Phe",
UUA:"Leu",
UUG:"Leu",
CUU:"Leu",
CUC:"Leu",
CUA:"Leu",
CUG:"Leu",
AUU:"Ile",
AUC:"Ile",
AUA:"Ile",
AUG:"Met",
GUU:"Val",
GUC:"Val",
GUA:"Val",
GUG:"Val",
/* - */
UCU:"Ser",
UCC:"Ser",
UCA:"Ser",
UCG:"Ser",
CCU:"Pro",
CCC:"Pro",
CCA:"Pro",
CCG:"Pro",
ACU:"Thr",
ACC:"Thr",
ACA:"Thr",
ACG:"Thr",
GCU:"Ala",
GCC:"Ala",
GCA:"Ala",
GCG:"Ala",
/* - */
UAU:"Tyr",
UAC:"Tyr",
UAA:"Stop",
UAG:"Stop",
CAU:"His",
CAC:"His",
CAA:"Gln",
CAG:"Gln",
AAU:"Asn",
AAC:"Asn",
AAA:"Lys",
AAG:"Lys",
GAU:"Asp",
GAC:"Asp",
GAA:"Glu",
GAG:"Glu",
/* - */
UGU:"Cys",
UGC:"Cys",
UGA:"Stop",
UGG:"trp",
CGU:"Arg",
CGC:"Arg",
CGA:"Arg",
CGG:"Arg",
AGU:"Ser",
AGC:"Ser",
AGA:"Arg",
AGG:"Arg",
GGU:"Gly",
GGC:"Gly",
GGA:"Gly",
GGG:"Gly",
};
const digit = ['U', 'C', 'A', 'G'];
function x() {
return Math.floor(Math.random()*4);
};
function form() {
return digit[x()]+digit[x()]+digit[x()]
}
let formed = form();
let arr = [obj[formed]];
function generateWrongOptions() {
for (i = 0; i < 4; i++) {
let wrong = obj[form()];
let arr2 = [];
for (i = 0; i < arr.length; i++) {
if (wrong!==arr[i]){
arr2.push('a');
};
if(arr2.length==arr.length){
arr.push(wrong)
}
else {
generateWrongOptions()
};
};
};
};
generateWrongOptions();
for (let n of arr) {
console.log(n)
}
Console returns Maximum calls exceeded;
On the other hand a similar code I wrote before creating this - as a guideline - to form an array of 4 different numbers works:
function x() {
return Math.floor(Math.random()*10)
}
let y = x();
let arr = [y];
function aa() {
for (i = 0; i < 4; i++) {
let z = x()
let arr2 = []
for (i = 0; i < arr.length ; i++)
{
if (z!==arr[i])
{arr2.push('a')};
}
if (arr2.length==arr.length)
{arr.push(z)}
else {aa()}
};
};
aa();
console.log(arr);
I think I can fix this code by declaring a new array of all the amino acids in the codon table (obj), but still want to know why the first code doesn't work while the latter does.
I'm not so sure if I understand your code correctly. However, I can see that you have two for loops in which you forgot to create a new variable:
you used "for (i .... )" , and you forgot to say "for (let i ..... )". Another issue i noticed is the redeclaration of "arr" in the last function, which I found weird since you already declared it outside of the function scope. In addition, there is an "arr2" that was also not declared with "let" or "var" words.

Dynamic variable declaration. Is this even the right method?

A little new to JS so be gentle :)
I'm trying to create a program that holds 5000+ boolean values that dynamically change based on other vars.
const chars = "abcdefghijklmnopqrstuvwxyz0";
const charsC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0"
const maxNum = 48;
const maxTile = 6;
var tile1, tile2, tile3, tile4, tile5, tile6
// test vars
var tile4 = "A27"
var t4a27 = false
// this snippet will be in an interval loop
for (let i = 1; i <= maxTile; ++i) {
for (let n = 0; n < chars.length; ++n) {
for (let j = 1; j <= maxNum; ++j) {
// this obviously doesnt work
var t[i][`${chars[n]}`][j];
// ^ ^ ^
if (tile[i] == `${charsC[n]}${j}`) {
t[i][h][j] = true;
console.log(t4a27)
} else {
t[i][h][j] = false;
}
}
}
}
For clarification a better word than "tile" for the vars could be "sprite" rather because its a point on the sprite.
The basic concept is the tile vars are designed to output their current position as a string value e.g. "A27". Then this loop will take that information and scan each tile subset to be true/false. So if the sprite lower right quadrant is inside "A27" the output would be t4a27 = true
In practice I can do this with just a lot of code (over 20,000 lines) but I figured their has to be an easier way that requires far less code.
This is probably not the right approach for your problem.
If you really need to store this amount of variables, it is probably best to put them in an object like so:
var tiles = {}
var tileName = 'abc'
// Dynamic setting:
tile[tileName] = true
// Dynamic reading:
console.log(tile[tileName])
I am wondering if you really want to store 5000 variables or if there is another way to calculate them at the time you need time, but that requires a bit more knowledge of the problem.
Javascript doesn't have this kind of ability to reflect local variables.
What you can do is attach all those variables to a global object, and proceed with: Object.keys(your_object) and your_object[key_name_here] = ...
I think you should use a 2-dim array for this. Or use a regular array of booleans with the appropriate size and do the index-magic yourself.
As you said, you are running on coordinates. A-27 is the same as row(1)+field(27) -- considering A is 1
If your field is 500x100, you create an Array as such: let gamefield = Array(500*100);
Warning: I have not tested this for syntax errors, but you should get the idea.
let gamefield = Array(500*100);
// optional gamefield.fill(true);
let row = idx => idx * 500;
let posIdx = (r, c) => row(r) + c;
// there is a sprite with a tiles property that returns
// 4 index positions for the sprite's quadrants as [r,c]
let quadrants = sprite.tiles.reportPositions()
// filter the quadrants where the gamefield at r,c is true
// this might also be a good case for some() instead of filter()
let collisions = quadrants.filter(pos => return gamefield[posIdx(...pos)]);
// if there is any of these, you can kill the sprite.
if(collisions.length > 0) sprite.kill();

Counter array in Javascript

I am trying to make two arrays. the unique array can get the elements (no repeats) from the text array, and the counter one can count the frequency of each elements. but something is wrong with the counter one.
var unique_array=new Array();
var counter_array=new Array();
var unique=true;
for (i=0;i<text_array.length;i++){
if (unique_array.length==0){
unique_array.push(text_array[0]);
counter_array.push(1);
}
else if(unique_array.length>0&&unique_array.length<=text_array.length){
for (j=0; j<unique_array.length;j++){
if (text_array[i]==unique_array[j]){
counter_array[j]=counter_array[j]+1;// something wrong with the
alert(counter_array[j]);
var unique=false;
}
}
if (unique==true){
unique_array.push(text_array[i]);
counter_array.push[1];
}
unique=true;
}
You could also simplify the code down using a hashmap and some ES5 higher-order functions:
var text_array = ["a1","a1","a2","a3","a2","a4","a1","a5"];
var counts = {};
text_array.forEach(function(el) {
counts[el] = counts.hasOwnProperty(el) ? counts[el]+1 : 1;
});
var unique_array = Object.keys(counts);
var counter_array=unique_array.map(function(key) { return counts[key]; })
You can do this much more simply using an object. Let the values be the keys of an object, then just increment the count of each property as you go. At the end, you can get an array of the unique keys and their values:
var text_array = ['foo','bar','foo','fum','fum','foo'];
var i = text_array.length;
var obj = {};
while (i--) {
if (obj.hasOwnProperty(text_array[i])) {
obj[text_array[i]]++;
} else {
obj[text_array[i]] = 1;
}
}
console.log('Unique values: ' + Object.keys(obj)); // Unique values: foo,fum,bar
console.log('Value counts: ' + Object.keys(obj).map(function(v){return obj[v]})); // Value counts: 3,2,1
Note that the sorting of counts in the output is purely coincidental.
As Jasvir posted, you can make it pretty concise:
var obj = {};
text_array.forEach(function(v) {
obj.hasOwnProperty(v)? ++obj[v] : obj[v] = 1;
});
But the first example is a bit easier to digest.
I think the approach is what's making it difficult. A hash table / associative array would be much easier to work with.
With a hash table (an object {} in JS), you can store each word in a key and increment the value of the key when you encounter the word again. Then, at the end, just go through the hash table and gather up all the keys which have small values. Those are your unique words.
function get_unique_words(text_array) {
var hash_table, i, unique_words, keys;
hash_table = {};
for(i = 0; i < text_array.length; i++) {
if(hash_table[text_array[i]] === undefined) {
hash_table[text_array[i]] = 1;
} else {
hash_table[text_array[i]]++;
}
}
// go through the hash table and get all the unique words
unique_words = [];
keys = Object.keys(hash_table);
for(i = 0; i < keys.length; i++) {
if(hash_table[keys[i]] === 1) {
unique_words.push(keys[i]);
}
}
return unique_words.sort();
}
console.log(get_unique_words(
['blah', 'blah', 'blah', 'goose', 'duck',
'mountain', 'rock', 'paper', 'rock', 'scissors']
));
Some issues and suggestions :
Don't use var twice for the same variable.
Browsers deal with it ok, but for clarity you should only be declaring your variables once.
Always localize your loop counters - forgetting a var before your i and j will cause them to become global variables.
This is relevant when you have a page with lots of code - all global variables will show up in the debugger's watch list at all times, making it harder to debug your code.)
Use the array literal notation [] instead of the function form Array.
The function form is longer and it's easier to forget the new. It's also easier to read (IMO).
Use more whitespace (it won't bite), such as before and after an equals sign:
var x = 1;
// vs.
var x=1;
It makes the code easier to read and most people don't overdo it.
Indent your code when it's inside a block (e.g. function, if, else, while, for, etc.).
This makes it easier to read the control flow of the code and will help prevent bugs.
Use three equals signs (===) unless you are using loose equality on purpose.
This will help someone looking at your code later (probably yourself) understand better what the test is supposed to be testing.

JavaScript For Loop Keeps Looping Infinity

I've written the functions below as part of a much larger application for processing FASTA formatted files via a web interface. For some reason it decided to run into infinity when call upon my baseCounts() function from within makePretty(). It might be worth noting that both functions are encapsulated by the same parent function.
The function baseCounts() returns valid data in the form of a 100+ long array, console.log confirms that it is not to blame so the problem has to be with makePretty().
Any help is welcome.
function baseCount(records){
// Count instances of Bases in array
var basecounts = Array();
for (i=0; i < records.length; i++){
var record = records[i];
console.log(record);
var count = [record.match(/A/g), record.match(/T/g), record.match(/C/g), record.match(/G/g)];
var basecount = Array();
for (i=0; i < count.length; i++){
basecount.push(count[i].length);
}
// return array of occurance
basecounts.push(basecount);
}
}
function makePretty(fasta){
// Make FASTA more human friendly
var data = Array();
var basecounts = Array();
var bases = Array();
console.log(fasta.length);
// Generate base array
for (i=1; i < fasta.length; i++){
bases.push(fasta[i][2])
}
basecounts = baseCount(bases); // RUNS INTO INFINITY
for (i=0; i < fasta.length; i++){
var record = Array();
record.push(i); // Add protein number
record.push(fasta[i][0]); // Add NC_#
record.push(fasta[i][1]); // Add base index
_record = fasta[i][2];
var l_record = _fasta.length; // Protein length
//var basecount = baseCount(_record);
var cg_content;
}
}
Your nested loops are using the same variable i, and clobbering each other's state.
for (i=0; i < records.length; i++){
...
for (i=0; i < count.length; i++){
...
}
Use distinct variables, say i and j or better yet pick meaningful names.
Also you should declare the variables (var i) to ensure they're local to the function.
Finally, use ++i, not i++. The former means "increment i" while the latter means "i, and oh by the way increment it". They both increment i, but the latter one returns the old value, which is a special language feature to use in special cases.
You're reseting your variable counter in your inner loop (i).
To avoid this, and future problems like it as well as hoisting issues, I would suggest using the newer functions such as forEach or map. You can also clean up your code this way:
function baseCountFunc(records){
// Count instances of Bases in array
var basecount = [];
records.forEach(function(record) {
var count = [record.match(/A/g), record.match(/T/g), record.match(/C/g), record.match(/G/g)];
count.forEach(function(countElement) {
basecount.push(countElement.length);
});
basecounts.push(basecount);
});
}
Also, I noticed you named your function the same name as your variables, you should avoid that as well.

Higher Order Functions - Eloquent JS

I have been reading through Chapter 5 last night and throughout the morning and can't seem to get the higher order functions concepts to stick. Here are the examples:
//I understand this first function, I am including it because it is used in the next function.
function forEach(array, action) {
for (vari = 0; i < array.length; i++)
action(array[i]);
}
forEach(["Wampeter", "Foma", "Granfalloon"], print);
function sum(numbers) {
var total = 0;
forEach(numbers, function(number) {
total += number;
});
return total;
}
To my understanding the function sum is taking the argument numbers, which I believe comes in as an array? Now, when the forEach function is called (within sum), it takes the array numbers passed to sum and then it also takes an anonymous function?
I am really confused on what this anonymous function is actually doing. It is taking the parameter number but what else is it doing? Does this anonymous function imply that in that parameter, a function like print or show will be passed the parameter number? In other words it would look something like this
function([10,12,11]) {
var total = 0
forEach([10,12,11]), show(???)
//at this point it would iterate over the array, and use the action passed to display `//the pointer in the array. What I think is happening is that it is taking this pointer value and adding it to the total.` //
I have been trying to wrap my head around this example for a while, if anyone knows of a good explanation or any other documentation to read over I would greatly appreciate it, thanks!
The anonymous function is applied to every currently selected element. You can see better how this works if you unroll (execute stepwise) the loop (pseudocode, * means current element):
var total = 0;
forEach([*1, 2, 3]), fun(1)) => total = 0 + 1 = 1
forEach([1, *2, 3]), fun(2)) => total = 1 + 2 = 3
forEach([1, 2, *3]), fun(3)) => total = 3 + 3 = 6
You can rewrite the sum function like this:
// because there is no "pass by reference" in JavaScript for
// "simple" types, total must be wrapped in an object
// in order to return the sum through the parameter for the showcase
var result = { total: 0 }
function sum(numbers_array) {
for (var i = 0; i < numbers_array.length; i++) {
accumulate(result, numbers_array[i]);
}
}
function accumulate(acc, number) {
acc.total += number;
}
In this case the accumulate function does the same as the anonymous function. When the accumulate function is declared within the scope of the sum function, then the total variable is like global (it is known) to the accumulate function and then there is no need of the first parameter, so the function becomes like the one you already know:
var total = 0;
function sum(numbers_array) {
function accumulate(number) {
total += number;
}
for (var i = 0; i < numbers_array.length; i++) {
accumulate(numbers_array[i]);
}
}
Next step would be to extract and pass the accumulate function as parameter:
var total = 0;
function accumulate(number) {
total += number;
}
// notice, that JavaScript knows how many parameters your function expects
function sum(numbers_array, action) {
for (var i = 0; i < numbers_array.length; i++) {
action(numbers_array[i]);
}
}
What left is to extract the iteration and the code will look like this one in the book.
Let me see if I can explain this easily for you:
The forEach() function accepts two parameters, the first one called array is obviously an array or an array-like object, the second parameter called action is actually a function.
forEach() visits each element in the array passed to it and applies to each element in the array the function passed to it as the second parameter.
So forEach() calls the function passed to it named action for each element in the array and it gives the function the array element as a parameter.
The function sum(numbers) accepts an array as you have though, and it uses forEach() inside itself to calculate the sum of numbers in that array using the anonymous function.
Remeber that the anonymous function is called once for each element in the array passed to sum() so it actually sums the elements in the array.
In simple words : to make your code more generic and concise.
Ex:
Lets say we want to find the max element in an Array :
That's pretty easy and cool :
In java script we will write :
var array = [10,20,30,40,50,60]
function maxEle(array){
var max = array[0];
for(var i=0;i< array.length;i++){
if(max < array[i]){
max = array[i];
}
}
console.log(max);
}
So this will give me the maximum element in an array.
Now after few days, some one asked me that your max is working pretty cool, I want a function which will print the minimum in an array.
Again I will redo the same thing, which i was doing in finding Max.
function minEle(array){
var min = array[0];
for(var i=0;i< array.length;i++){
if(min > array[i]){
min = array[i];
}
}
console.log(min);
}
Now this is also working pretty cool.
After sometime, another requirement comes up : I want a function which will print the sum of all the elements of the array.
Again the code will be similar to what we have written till now, except now it will perform summation.
function sumArr(array){
var sum = 0;
for(var i=0;i< array.length;i++){
sum = sum + array[i];
}
}
console.log(sum);
}
Observation :
After writing these bunch of codes, I m rewriting almost the same thing in every function, iterating over the Array and then performing some action.
Now writing the repetitive code is not a cool stuff.
Therefore we will try to encapsulate the varying part i.e action viz min, max, summation.
Since its feasible to pass functions as arguments to a function in FPL.
therefore we will re-factor our previously written code and now write a more generic function.
var taskOnArr = function(array, task){
for(var i=0;i<array.length;i++){
task(array[i]);
}
}
Now this will be our generic function, which can perform task on each element of Array.
Now our tasks will be :
var maxEle = array[0];
var taskMaxEle = function(ele){
if(maxEle < ele){
maxEle = ele;
}
}
Similarly for min element :
var minEle = array[0];
var taskMinEle = function(ele){
if(minEle > ele){
minEle = ele;
}
}
Also for summation of Array :
var sum = 0;
var taskSumArr = function(ele){
sum = sum + ele;
}
Now we need to pass functions to taskOnArr function :
taskOnArr(array,taskSumArr);
console.log(sum);
taskOnArr(array,taskMinEle);
console.log(minEle);
taskOnArr(array,taskMaxEle);
console.log(maxEle);

Categories