How to find the count of images that have same file name? - javascript

Can you please help me how to find the no.of images for same file name,
var images =["Cat.png", "Cock.png","Dog.png","Parrot.png","Penguin.png",
"Rabbit.png","Parrot.png"];
here I have 7 images in the array...
I need count like..
Cat:1
Parrot :2
Penguin:1
Please give me the suggestion
Thanks,
Rajasekhar

The usual solution is to use an object as a map to make the link between the keys (name of the files) and the count :
var count = {};
for (var i=images.length; i-->0;) {
var key = images[i].split(".")[0]; // this makes 'Parrot' from 'Parrot.png'
if (count[key]) count[key]++;
else count[key] = 1;
}
Then you have, for example count['Parrot'] == 2
Demonstration : http://jsfiddle.net/tS6gY/
If you do console.log(count), you'll see this on the console (Ctrl+Uppercase+i on most browsers) :
EDIT about the i--> as requested in comment :
for (var i=images.length; i-->0;) {
does about the same thing than
for (var i=0; i<images.length; i++) {
but in the other directions and calling only one time the length of the array (thus being very slightly faster, not in a noticeable way in this case).
This constructs is often used when you have a length of iteration that is long to compute and you want to do it only once.
About the meaning of i--, read this.
i-->0 can be read as :
decrements i
checks that the value of i before decrement is strictly positive (so i used in the loop is positive or zero)

Not sure about efficiency, but this should do:
var images =["Cat.png", "Cock.png","Dog.png","Parrot.png","Penguin.png","Rabbit.png","Parrot.png"];
images.forEach(function(img){
var count = 0;
images.forEach(function(image, i){
if(img === image){
delete images[i];
count++;
}
});
console.log(img, count);
});
DEMO

You can keep unique keys in an array and use another array for counting the frequency:
var images =["Cat.png", "Cock.png","Dog.png","Parrot.png","Penguin.png","Rabbit.png","Parrot.png"];
var counts = [];
var keys = [];
for (i = 0; i < images.length; i++){
if (!counts[images[i]]) {
counts[images[i]] = 0;
keys.push(images[i]);
}
counts[images[i]]++;
}
for (i = 0; i < keys.length; i++) alert(keys[i] + " : " + counts[keys[i]]);
​
Here is a demo : http://jsfiddle.net/e5zFC/1/

Related

shift changes the length of the array so the last element is not going to be executed

In JavaScript, for a array, if methods such as pop, shift is used, the length of array changes as well. In my JS code below, it never executes the third elements 'Ds3' in the array since after the notes.shift() is executed, the length of the array becomes 0 so it just jumps out of the for loop, I do not know how to change the code so it can actually execute the 'Ds3'. Hope someone could help me out. Thank you in advance.
Code 1:
$(document).ready(function() {
var notes = ['F2', 'As2','Ds3'];
for(i = 0; i < notes.length; i++) {
$('#_' + notes.shift()).addClass('just_do_it');
alert(notes.length);
}
});
For code 2, I do not know why when I sort of make the one line code to two liner, the code does not work at all. Thank you in advance.
code 2:
$(document).ready(function() {
var notes = ['F2', 'As2','Ds3'];
var count = 0;
for(i = 0; i < notes.length; i++) {
var note = notes.shift();
$('#_' + note).addClass('just_do_it');
count++;
alert(notes.length);
}
});
Is there a reason why you want to empty that array? If insist on it, try changing to a while loop.
var notes = ['F2', 'As2','Ds3'];
var count = 0;
while(notes.length > 0){
var note = notes.shift();
$('#_' + note).addClass('shown');
count++;
alert(notes.length);
}
If I may add, you're also incrementing the count as you loop through the array. Rather you can get the count immediately just by getting the length of the array like this var count = notes.length
Also since you mentioned pop and shift arrays methods, you should checkout other array methods such as forEach, map or reduce
Since shift() is indeed destructive you could simply use the index of that iteration in the loop and leave the array unaltered
for(i = 0; i < notes.length; i++) {
// switch from `notes.shift() to notes[i]
$('#_' + notes[i]).addClass('just_do_it');
count++;
alert(notes.length);// length remains unchanged
}
Or using join() to create a selector for all and not use any loop
$('#_' + notes.join(',#_') ).addClass('just_do_it');
You could also try:
for (var count = notes.length; count > 0; count--) {
$('#_' + notes.shift()).addClass('just_do_it');
}
or
while (notes.length > 0) {
$('#_' + notes.shift()).addClass('just_do_it');
}

JS check if the value of object exists

So, I have following js setup:
var NAMES = [];
function INFO(id,first,middle,last){
var newMap = {};
newMap[id] = [first, middle, last];
return newMap ;
}
Then,
for (var j = 0; j < NUMBER.length; j++) { //let say it there are three values
var my_name = all_names[j]; // has "185, 185, 185"
if (NAMES[my_name] !== 185){ //Needs to check here
NAMES.push(INFO(my_name,"sean","sdfsd","sdfsfd"));
}else{
}
}
alert(JSON.stringify(NAMES , null, 4));
Here is a screenshot of the alert:
I hardcoded the number "185" for this example. I need to check if the id of 185 exists, then skip to else. I am not sure how to check it. I tried typeof, undefinedetc. but no luck.
(In other words, I should only have one "185").
Any help? Thanks!
If I understood correctly what you are trying to achieve, you have to iterate over NAMES and check every element. For example, you could do it using [].some javascript function:
if (!NAMES.some(function(v){return v[my_name]})) {
...
} else {
}
If you want to remove duplication you can just use NAMES as an object instead of array like this
var all_names = [185, 185, 181],
NAMES = {};
for (var j = 0; j < all_names.length; j++) { //let say it there are three values
var my_name = all_names[j]; // has "185, 185, 185"
NAMES[my_name] = ["sean","sdfsd","sdfsfd"];
}
alert(JSON.stringify(NAMES, null, 4));
First of all I would recommend making a JS Fiddle or CodePen out of this so people can see the code running.
I believe that the issue is that NAMES[my_name] is not doing what you think it is. NAMES is an Array so when you say NAMES[my_name] you are really asking for the ITEM in the array so you are getting the entire object that you create in the INFO function. What you really want is to see if the object has an attribute that matches the value (e.g. "185" from the my_names array).
This is not the prettiest code but it will show you how to do what you really want to do:
var NAMES = [];
function INFO(id,first,middle,last){
var newMap = {};
newMap[id] = [first, middle, last];
return newMap ;
}
all_names = ["185", "186", "185"]
for (var j = 0; j < all_names.length; j++) {
var my_name = all_names[j];
if (NAMES.length == 0) {
NAMES.push(INFO(my_name,"sean","sdfsd","sdfsfd"));
} else {
var match = false;
for (var x = 0; x < NAMES.length; x++) {
console.log(NAMES[x][my_name] + ' : ' + my_name);
if(NAMES[x][my_name]) {
match = true;
}
}
if (!match) {
NAMES.push(INFO(my_name,"sean","sdfsd","sdfsfd"));
}
}
}
alert(JSON.stringify(NAMES , null, 4));
Note the if that looks at NAMES[x][my_name] - this is asking if the item at array index 'x' has an attribute of 'my_name' (e.g. "185"). I believe this is really what you are trying to do. As its after midnight I assure you that there is more concise and pretty JS to do this but this should show you the basic issue you have to address.
Try this code using hasOwnProperty method :
for (var j = 0; j < NUMBER.length; j++) { //let say it there are three values
var my_name = all_names[j]; // has "185, 185, 185"
if (!NAMES[my_name].hasOwnProperty("185")){ //Needs to check here
NAMES.push(INFO(my_name,"sean","sdfsd","sdfsfd"));
}else{
}
}

Using search method from string

I'm trying to count the number of times certain words appear in the strings. Every time I run it I get a
uncaught TypeErro: undefined is not a function
I just actually need to count the number of times each "major" appears.
Below is my code:
for(var i = 0; i < sortedarray.length; i++)
{
if(sortedarray.search("Multimedia") === true)
{
multimedia += 1;
}
}
console.log(multimedia);
Here is my csv file which is stored in a 1d array.
"NAME","MAJOR","CLASS STANDING","ENROLLMENT STATUS"
"Smith, John A","Computer Science","Senior","E"
"Johnson, Brenda B","Computer Science","Senior","E"
"Green, Daisy L","Information Technology","Senior","E"
"Wilson, Don A","Information Technology","Junior","W"
"Brown, Jack J","Multimedia","Senior","E"
"Schultz, Doug A","Network Administration","Junior","E"
"Webber, Justin","Business Administration","Senior","E"
"Alexander, Debbie B","Multimedia","Senior","E"
"St. John, Susan G","Information Technology","Junior","D"
"Finklestein, Harold W","Multimedia","Freshman","E"
You need to search inside each string not the array. To only search inside the "Major" column, you can start your loop at index 1 and increment by 4 :
var multimedia = 0;
for(var i = 1; i < sortedarray.length; i += 4)
{
if(sortedarray[i].indexOf("Multimedia") > -1)
{
multimedia += 1;
}
}
console.log(multimedia);
What you're probably trying to do is:
for(var i = 0; i < sortedarray.length; i++)
{
if(sortedarray[i].indexOf("Multimedia") !== -1)
{
multimedia++;
}
}
console.log(multimedia);
I use indexOf since search is a bit of overkill if you're not using regexes.
Also, I replaced the += 1 with ++. It's practically the same.
Here's a more straightforward solution. First you count all the words using reduce, then you can access them with dot notation (or bracket notation if you have a string or dynamic value):
var words = ["NAME","MAJOR","CLASS STANDING","ENROLLMENT STATUS"...]
var count = function(xs) {
return xs.reduce(function(acc, x) {
// If a word already appeared, increment count by one
// otherwise initialize count to one
acc[x] = ++acc[x] || 1
return acc
},{}) // an object to accumulate the results
}
var counted = count(words)
// dot notation
counted.Multimedia //=> 3
// bracket notation
counted['Information Technology'] //=> 3
I don't know exactly that you need this or not. But I think its better to count each word occurrences in single loop like this:
var occurencesOfWords = {};
for(var i = 0; i < sortedarray.length; i++)
{
var noOfOccurences = (occurencesOfWords[sortedarray[i]]==undefined?
1 : ++occurencesOfWords[sortedarray[i]]);
occurencesOfWords[sortedarray[i]] = noOfOccurences;
}
console.log(JSON.stringify(occurencesOfWords));
So you'll get something like this in the end:
{"Multimedia":3,"XYZ":2}
.search is undefined and isn't a function on the array.
But exists on the current string you want to check ! Just select the current string in the array with sortedarray[i].
Fix your code like that:
for(var i = 0; i < sortedarray.length; i++)
{
if(sortedarray[i].search("Multimedia") === true)
{
multimedia += 1;
}
}
console.log(multimedia);

Writing a recursive function which iterates through an unknown depth of nested loops

Given an array of values:
var values = new Array();
array.push(2);
array.push(3);
array.push(4);
I'd like to create an iterative function which can store every possible combination of values, for any length of array.
For example, in this case the possible values would be (1,1,1)(1,1,2)(1,1,3)(1,1,4)(1,2,1)(1,2,2)(1,2,3)(1,2,4)(2,1,1)(2,1,2)(2,1,3)(2,1,4)(2,2,1)(2,2,2)(2,2,3)(2,2,4)
I know that to do this I need to use an recursive function, which will go a level deeper and call the function again if the maximum depth has not been reached...
I know where to start is (probably, I think)
function iterativeLoop(level, depth) {
for(var i = 0; i < values.length; i++) {
if(level < depth) {
iterativeloop(level+1, depth);
}
else if (level=depth) {
}
}
}
I'm not sure how I can access the 'upper' levels once the function is called deeper though... i.e. I'm not sure how to access (1,2,4) and not just (?,?,4)
I hope that makes sense?
(Sorry I know my title isn't very good, I couldn't think how to concisely explain it)
I'm not sure how I can access the 'upper' levels once the function is called deeper though... i.e. I'm not sure how to access (1,2,4) and not just (?,?,4)
You will need to pass them on, e.g. in an array.
for(var i = 0; i < values.length; i++)
This should not be the outer iteration to perform, unless you want to construct a two-dimensional array of results in a simple nested loop (see below). Instead, you want value.length to be the depth you are recursing to. On every recursion level, you will iterate from 1 to values[level] then. And instead of passing a level, we will pass an array of the current state (the question marks from above) whose length is the level.
var values = [2,3,4];
function recurse(state) {
var level = state.length;
var depth = values.length;
if (level == depth) {
console.log.apply(console, state); // or whatever you want to do
} else {
for (var i=1; i<=values[level]; i++) {
state.push(i); // save current question mark
// notice state.length = level + 1 now
recurse(state); // enter next level
state.pop(); // delete it after we're so state doesn't grow infinitely :-)
}
}
}
recurse([]);
If you want to use your iteration over the values, you can do so by adding more and more states to a result array (growing by one value each level), which in the end will contain all possible combinations:
var values = [2,3,4];
var result = [[]]; // one empty state at level 0
for (var i=0; i<values.length; i++) {
var reslen = result.length,
val = values[i];
var mult = []; // will become the new result with a length of (reslen * val)
for (var j=0; j<reslen; j++) {
for (var k=1; k<=val; k++) {
var state = result[j].slice(); // make a copy
state.push(k);
mult.push(state);
}
}
result = mult;
}
// logging the `result` on each level will show us
// 0 - [[]]
// 1 - [[1],[2]]
// 2 - [[1,1],[1,2],[1,3],[2,1],[2,2],[2,3]]
// 3 - [[1,1,1],[1,1,2],[1,1,3],[1,1,4],[1,2,1],[1,2,2],[1,2,3],[1,2,4],[1,3,1],[1,3,2],[1,3,3],[1,3,4],[2,1,1],[2,1,2],[2,1,3],[2,1,4],[2,2,1],[2,2,2],[2,2,3],[2,2,4],[2,3,1],[2,3,2],[2,3,3],[2,3,4]]
You can see how this is similar to #Jason's approach.
You don't need recursion since the length of the arbitrary data set is defined at the beginning at runtime:
var numbers = [2,3,4];
var result_array = [];
var num_product = 1;
var i=0, j=0, k=0; // iterators
for (i=0; i<numbers.length; i++) {
num_product *= numbers[i];
}
for (i=0; i<num_product; i++) {
result_array.push([]);
}
for (i=0; i<result_array.length; i++) {
product = 1;
for (j=0; j<numbers.length; j++) {
k = (Math.floor(i/product)%numbers[j]) + 1;
product *= numbers[j];
result_array[i][j] = k;
}
}
tested and functional for any number of array elements.
A side-by-side benchmark shows this code to be significantly faster than the recursive code - if you are able to avoid recursion (e.g. you know enough information up front to be able to define the whole problem) then it's better to do so, and the problem as currently defined allows you to do that. If you're just trying to learn about recursion, then this isn't very helpful to you :)

Javascript: matching a dynamic string against an array

I'm attempting to teach myself javascript. I chose something I assumed was simple, but ran into problems relatively quickly.
I'm attempting to search a string for another string given by the user.
My code so far is:
var source = "XREs2qqAQfjr6NZs6H5wkZdOES5mikexRkOPsj6grQiYNZfFoqXI4Nnc1iONKVrA";
var searchString = []; //the users input
searchString = prompt("Enter search string");
var hits = [];
var one = 0;
var two = 0;
var k = 0;
var sourceSearch = function(text) {
for(i = 0; i < source.length; i++) { //for each character in the source
if(source[i] === searchString[0]) { //if a character in source matches the first element in the users input
one = source.indexOf(i); //confused from here on
for(p = searchString.length; p > 0; p--) {
}
}
}
};
sourceSearch(searchString);
My idea was:
check to see if the first loop finds a character that matches the first character in the user input
if it matches, check to see if the next X characters after the first match the next X characters in the source string
if they all match, push them to the hits array
My problem: I have no idea how to iterate along the arrays without nesting quite a few if statements, and even then, that wouldn't be sufficient, considering I want the program to work with any input.
Any ideas would be helpful. Thanks very much in advance.
Note: There are a few un-used variables from ideas I was testing, but I couldn't make them work.
You can try:
if (source.indexOf(searchString) !== -1) {
// Match!
}
else
{
//No Match!
}
As the other answers so far point out, JavaScript strings have an indexOf function that does what you want. If you want to see how it's done "by hand", you can modify your function like this:
var sourceSearch = function(text) {
var i, j, ok; // always declare your local variables. globals are evil!
// for each start position
for(i = 0; i < source.length; i++) {
ok = true;
// check for a match
for (j = searchString.length - 1; ok && j >= 0; --j) {
ok = source[i + j] === searchString[j];
}
if (ok) {
// searchString found starting at index i in source
}
}
};
This function will find all positions in source at which searchString was found. (Of course, you could break out of the loop on the first success.) The logic is to use the outer loop to advance to each candidate start position in source and use the inner loop to test whether that position actually is the position of a match to searchString.
This is not the best algorithm for searching strings. The built-in algorithm is much faster (both because it is a better algorithm and because it is native code).
to follow your approach, you can just play with 2 indexes:
var sourceSearch = function(text) {
j = 0;
for(i = 0; i < source.length; i++) {
if(source[i] === text[j]) {
j++;
} else {
j = 0;
}
if (j == text.length) {
console.log(i - j); //this prints the starting index of the matching substring
}
}
};
These answers are all pretty good, but I'd probably opt for something like this:
var source = "XREs2qqAQfjr6NZs6H5wkZdOES5mikexRkOPsj6grQiYNZfFoqXI4Nnc1iONKVrA";
var searchString = []; //the users input
searchString = prompt("Enter search string");
var hits = source.split(searchString);
var hitsCount = hits.length - 1;
This way you have all of the data you need to figure out where each hit occurred in he source, if that's important to you.

Categories