Count number of elements in an array using Javascript - javascript

I have an assignment for a Javascript course where I have to count how many of each specific types of elements occur in an array. The array is 105 elements long, and just occurrences of the numbers 1, 2, 3, 4, and 5. I have to count how many 1's, 2's, 3's, etc.
Of course there's a simple way to do this using a loop however my teacher has added the following at the end of the assignment:
Use only the length property, toString(), sort() and indexOf() methods. Please no loops or conditional statements.
I have no idea how to do this assignment without using a loop. Any help you can give me is greatly appreciated. Thanks!

this will be the answere:
var c=[1,2,3,4,5,2,3,4,5]
c.sort()
cout_of_1 = c.indexOf(2)-c.indexOf(1);
cout_of_2 = c.indexOf(3)-c.indexOf(2);
cout_of_3 = c.indexOf(4)-c.indexOf(3);
cout_of_4 = c.indexOf(5)-c.indexOf(4);
cout_of_5 = c.length-c.indexOf(5)+1;

Since this is an assignment and you haven't really shown an attempt, I'll just give you a couple of hints.
Once you sort the array, all of the 1s will be grouped together at the start of the array, then all the 2s, etc.
The indexOf function returns the first index at which a given element can be found in the array, or -1 if it is not present.
Given the index of the first occurrence of each digit in a sorted array, you should be able to calculate how many of each digit there are. I'm not sure you'll need toString() at all. Your instructor might have thrown that in to be sneaky.

First, sort the array, then grab the first occurrence of the next value. That's the amount of numbers you have, minus the ones you already have.
var array = [1,2,5,3,2,4,5,2,1,3,3,4,5,6,2];
array = array.sort();
var ones = array.indexOf(2);
var twos = array.indexOf(3) - ones;
var threes = array.indexOf(4) - ones - twos;
...
However for the last value (5) there is no next value to check. You can work around this by checking the length and subtracting one from it.
var fives = array.length - ones - twos - threes - fours;
Keep in mind that this is actually bad code, and you should use loops.

Related

Sorting a dynamically filled array of objects

I have an array that is initialized like such var generationObject = [{string:"", score: 0}];
which I then fill dynamically:
for(var i = 0; i < amount_offspring; i++)
{
// "load" text into array and send the string to see if it evolves
generationObject[i].string = evolve(start_text, characters, mutation_rate);
// then score the string
generationObject[i].score = score(target_text, generationObject.string);
}
I then want to sort this array by score. I don't know what's best, to sort it in the for loop or sort the entire array afterwards.
I will then take the string of the highest scoring object and pass it through the function again, recursively.
So what would be a good way to go about this sort function? I've seen some here use this
generationObject.sort(function(a, b) {
return (a.score) - (b.score);
});
But I'm not sure if .sort is still supported? This didnt seem to work for me though.
generationObject is an array, not an object, so score(target_text, generationObject.string); could be the problem, as .string will be undefined. (Did you mean generationObject[i].string?)
Try building your array like this:
var generationObject = []
for(var i = 0; i < amount_offspring; i++)
{
evolved_string = evolve(start_text, characters, mutation_rate)
generationObject.push({
string: evolved_string,
score: score(target_text, evolved_string)
})
}
And then Array.prototype.sort should do the trick.
You should write your sorting logic outside the for loop, since if you put it inside, the object array will be sorted N times, where N being the iterations of your loop. The following are two ways to do it-
By using sort() function- To clarify your question, sort() is still supported across almost all the browsers. If you are still concerned about the browser compatibility, you can check the MDN documentation to see the list of supported browsers.
generationObject = generationObject.sort(function(a, b) {
return parseInt(a.score) - parseInt(b.score);
});
By using underscorejs-
In underscore, you can take advantage of the sortBy() function.
Returns a (stably) sorted copy of list, ranked in ascending order by the results of running each value through iteratee. iteratee may also be the string name of the property to sort by (eg. length).
You can simply do this in underscorejs-
generationObject = _.sortBy(generationObj, 'score');

Can someone explain to me why this loop doesn't give me the desired result?

Basically, I'm writing a little algorithm that takes in a random array with only numbers and spits out the 2nd highest number in the array (assuming all entries in the array are numbers and there are at least 2 entries). Here is the code:
var secondGreatest = function(numberArray){
var array = numberArray;
var result = [];
for(var i = 0; i < array.length; i++){
if(array[i] === Math.max.apply(Math, array)){
result.push(array[i]);
array.splice(i, 1);
}
};
return result[1];
};
So what I'm doing is setting the input array of numbers to variable "array". Then I set variable "result" to an empty array.
In the for loop, I specify that if the array at the ith position equals the highest number of the array, push that number into the empty array and remove that number from the original array. Since the "result" array will have the order from highest to lowest number, I call result[1] to give me the 2nd highest number.
However, the result array only contains one entry and it's the highest number of the previous array. After that, the for loop seems to stop. I tried the "continue;" statement, but nothing works.
Any help as to why this doesn't work is appreciated.
Here is a shorter code, if you want to keep using the Math.max method.
var secondGreatest = function(numberArray){
var top1 = Math.max.apply(Math, numberArray);
numberArray.splice(numberArray.indexOf(top1));
return Math.max.apply(Math, numberArray);
};
var arr = [1,3,5,7,4,2];
alert(secondGreatest(arr));
You don't really need to iterate, and actually iterating would make it necessary to reset the for whenever you remove the max item. Tushar's answer in the comment is more compact though, and problably makes more sense.
When you do a splice, the array is being re-indexed and array.length which was cached becomes obsolete. This is why the for loop stops. You can start at the end and iterate backwards to fix this.

Checking if element exists in array without iterating through it

my array:
tempListArray = "[{"id":"12","value":false},{"id":"10","value":false},{"id":"9","value":false},{"id":"8","value":false}]";
To check if an element exists I would do this:
for (var i in tempListArray) {
//check flag
if (tempListArray[i].id == Id) {
flagExistsLoop = 1;
break;
}
}
Is there anyway, I can check if an Id exists without looping through the whole array. Basically I am worried about performance if say I have a 100 elements.
Thanks
No, without using custom dictionary objects (which you seriously don't want to for this) there's no faster way than doing a 'full scan' of all contained objects.
As a general rule of thumb, don't worry about performance in any language or any situation until the total number of iterations hits 5 digits, most often 6 or 7. Scanning a table of 100 elements should be a few milliseconds at worst. Worrying about performance impact before you have noticed performance impact is one of the worst kinds of premature optimization.
No, you can't know that without iterating the array.
However, note for...in loops are a bad way of iterating arrays:
There is no warranty that it will iterate the array with order
It will also iterate (enumerable) non-numeric own properties
It will also iterate (enumerable) properties that come from the prototype, i.e., defined in Array.prototype and Object.protoype.
I would use one of these:
for loop with a numeric index:
for (var i=0; i<tempListArray.length; ++i) {
if (tempListArray[i].id == Id) {
flagExistsLoop = 1;
break;
}
}
Array.prototype.some (EcmaScript 5):
var flagExistsLoop = tempListArray.some(function(item) {
return item.id == Id;
});
Note it may be slower than the other ones because it calls a function at each step.
for...of loop (EcmaScript 6):
for (var item of tempListArray) {
if (item.id == Id) {
flagExistsLoop = 1;
break;
}
}
Depending on your scenario, you may be able to use Array.indexOf() which will return -1 if the item is not present.
Granted it is probably iterating behind the scenes, but the code is much cleaner. Also note how object comparisons are done in javascript, where two objects are not equal even though their values may be equal. See below:
var tempListArray = [{"id":"12","value":false},{"id":"10","value":false},{"id":"9","value":false},{"id":"8","value":false}];
var check1 = tempListArray[2];
var check2 = {"id":"9","value":false};
doCheck(tempListArray, check1);
doCheck(tempListArray, check2);
function doCheck(array, item) {
var index = array.indexOf(item);
if (index === -1)
document.write("not in array<br/>");
else
document.write("exists at index " + index + "<br/>");
}
try to use php.js it may help while you can use same php function names and it has some useful functionalities
There is no way without iterating through the elements (that would be magic).
But, you could consider using an object instead of an array. The object would use the (presumably unique) id value as the key, and the value could have the same structure you have now (or without the redundant id property). This way, you can efficiently determine if the id already exists.
There is a possible cheat for limited cases :) and it is magic...cough cough (math)
imagine you have 3 elements:
1
2
3
and you want to know if one of these is in an array without iterating it...
we could make a number that contains a numerical flavor of the array. we do this by assigning prime numbers to the elements:
1 - 2
2 - 3
3 - 5
the array so when we add item 2 we check that the array doesn't already contain the prime associated to that item by checking (if Flavor!=0 && (Flavor%3)!=0) then adding the prime Flavor*=3;
now we can tell that the second element is in the array by looking at the number.
if Flavor!=0 && (Flavor%3)==0 // its There!
Of course this is limited to the numerical representation that can be handled by the computer. and for small array sizes (1-3 elements) it might still be faster to scan. but it's just one idea.
but the basis is pretty sound. However, this method becomes unusable if you cannot correlate elements one to one with a set of primes. You'll want to have the primes calculated in advance. and verify that the product of those is less numerical max numerical representation. (also be careful with floating-point. because they might not be able to represent the number at the higher values due to the gaps between representable values.) You probably have the best luck with an unsigned integer type.
This method will probably be too limiting. And there is something else you can do to possibly speed up your system if you don't want to iterate the entire array.
Use different structures:
dictionaries/maps/trees etc.
if your attached to the array another method can be a bloom filter. This will let you know if an element is not in your set, which can be just as useful.

Most computationally efficient way to find last element in a JavaScript Array?

Would it be faster to use
var lastelement = myarray[myarray.length - 1];
or
var lastelement = myarray.reverse()[0];
and why?
Just think about it.
If you know how long an array is, it is much faster to just get the last value than to have to compute the reverse!
It is faster to access an element by its index, as it should have O(1) complexity. Reversing an array and then accessing the first index, on the other hand, would have at least O(n) complexity, depending on how the reversing algorithm is implemented.
I'll take this from a different angle than has been answered here. Chances are you just want to get the last element, you don't want to do anything to the actual array itself. If you use array.reverse to get the last element, you are actually changing the array (probably an unpleasant side effect in your case).
var myArray = [.....]; // some array
var lastElement = myArray.reverse()[0]; // get the last element
var firstElement = myArray[0]; // tricked you! This is now the same as
// lastElement because the myArray object
// in memory has been reversed.
So if you want to get the last element without changing the array you'd have to do this:
var myArray = [.....]; // some array
var lastElement = myArray.slice().reverse()[0]; // copy and get the last element
var firstElement = myArray[0]; // this is the correct first element
Pretty obvious which way is more efficient now.
Array.reverse() replacing old array with new reversed array in same reference ,crating the new array with new elements is much slower than get array element by index.
var lastelement = myarray[myarray.length - 1];
Is much faster.
The real efficient solution is to use a red and black binary tree (http://en.wikipedia.org/wiki/Red%E2%80%93black_tree ) where you'll store in each node one array value, the delta with the previous and next item, as well as the relative position to median. Then with only a few traversal you should be able to identify the last element (last element is the one having an index with biggest spread to median index, while having a previous item and no next item).
The trick is that each traversal takes only O(ln(n)) and since you do less than ln(n) traversal, time is below O(sq(ln(n))), so it's very fast.
Edit : following Bergi's constructive comments, i just wonder if it wouldn't be faster to just use arrays for this, by using a Fast fourier transform on an array containing all indexes of the array, then identifying last element with a frequency analysis, then convert back the array to get the number out of the frequency. I apologize if i'm unclear, i don't see clearly all steps at the time of writing, but i think it's a idea worth following.

Javascript/jQuery Id check to drive numbering function with validation

I need help with a loop... it's probably simple but I'm having difficulty coding it up.
Basically, I need to check existing Ids for their number so I can create a unique id with a different number. They're named like this: id="poly'+i'" in sequence with my function where i is equal to the number of existing elements. Example: Array 1, Array 2, Array 3 corresponding with i=1 for the creation of Array 1, i=2 for Array 2, etc.
Right now i is based on the total number of existing elements, and my "CreateNew" function is driven off x=i+1 (so the example above, the new element will be named Array 4). The problem is that if you delete one of the middle numbers, the "Create" function will duplicate the high number. i.e. Array 1, 2, 3 delete 2, create new-> Array 1, 3, 3.
I need an if() statement to check if the array already exists then a for() loop to cycle through all i's until it validates. Not sure how to code this up.
The code I'm trying to correct is below (note I did not write this originally, I'm simply trying to correct it with my minimal JS skills):
function NewPanel() {
var i = numberOfPanels.toString();
var x = (parseInt(i)+1).toString();
$('#items').append('<div onclick="polygonNameSelected(event)" class="polygonName" id="poly'+i+'"> Array '+ x +' </div>');
$('div[id*=poly]').removeClass('selected');
$('#poly'+i).addClass('selected');
$('#poly'+i).click(function() {
selectedPolygon = i;
$('div[id*=poly]').removeClass('selected');
$(this).addClass('selected');
});
}
THANK YOU! :)
Please clarify "The problem is that if you delete one of the middle numbers, ". What do you mean by delete? Anyway, the simplest solution is to create two arrays. Both arrays will have the same created id's. Whenever an id is created in the first array, an id will be added to the second array. So when it is deleted from first array, check your second array's highest value and then create this id in first array. I hope this did not confuse you.
Well it is hard to tell why you cannot just splice the array down. It seems to me there is a lot of extra logic involved in the tracking of element numbers. In other words, aside from the index being the same, the ids become the same as well as other attributes due to the overlapping 1, 3, 3 (from the example). If this is not the case then my assumption is incorrect.
Based on that assumption, when I encounter a situation where I want to ensure that the index created will always be an appending one, I usually take the same approach as I would with a database primary key. I set up a field:
var primaryKeyAutoInc = 0;
And every time I "create" or add an element to the data store (in this case an array) I copy the current value of the key as it's index and then increment the primaryKeyAutoInc value. This allows for the guaranteed unique indexing which I am assuming you are going for. Moreover, not only will deletes not affect future data creation, the saved key index can be used as an accessor.

Categories