1

I'm trying to rewrite this frequency finding program in Javascript. Here is the Java code:

public class frequency {
   public static void main(String[] args){
       String S = "Temple University";   
       int[] p = new int[256];
       for (char c :S.toCharArray()) {
           p[c]++;
           System.out.println(c +" shows up "+p[c] + " times");
       }

Output:

T shows up 1 times
e shows up 1 times
m shows up 1 times
p shows up 1 times
l shows up 1 times
e shows up 2 times
  shows up 1 times
U shows up 1 times
n shows up 1 times
i shows up 1 times
v shows up 1 times
e shows up 3 times
r shows up 1 times
s shows up 1 times
i shows up 2 times
t shows up 1 times
y shows up 1 times

However, my JavaScript implementation doesn't work at all:

  function frequency(){
  s = "Temple University";
  str = s.split('');
  p = [];
  p.length = 256;
  console.log("start");
  for(c in str){
    p[c]++;
    console.log("inside" + c);
    console.log(String.fromCharCode(c) + " shows up " + p[c] + "times");
  }
}

It's late I've been trying to figure out why this JavaScript code is not working so I'm sorry if this post seems unpolished.

4 Answers 4

1

You can manipulate string directly as array and need a safe check for occurrence of chars else assign value 1.

So use a for loop for iterating over whole string can extract char as s[index] while using p[char] for occurrence frequency.

sample code follows

function frequency(){
  s = "Temple University";
  p = [];
  console.log("start");
  for(var i=0;i<s.length;i++){
    if(!p[s[i]]){
      p[s[i]] = 1;
    }else{
      p[s[i]]++;  
    }
    console.log(s[i] + " shows up " + p[s[i]] + "times");
  }
}

frequency()

Sign up to request clarification or add additional context in comments.

Comments

1

Does this work for you? If so, you just weren't referencing the charCode but the index of the letter in the string..

function frequency() {
	s = "Temple University";
	str = s.split('');
	p = [];
	p.length = 256;
	console.log("start");
	for (c in str) {
		var curChar = str[c];
		var charCode = curChar.charCodeAt();
		p[charCode] ? p[charCode]++ : p[charCode] = 1;

		console.log(curChar + " shows up " + p[charCode] + " time(s)");
	}
}

frequency()

Comments

1

The main reason this isn't working is that for loops work differently in Javascript than in Java. In Javascript, a for-in loop iterates through the properties of an object, not the indices of an array or string, so rather than for-in, you'd want to use a plain for loop, like so:

function getFrequencies(string) {
    if (typeof(string) !== 'string') {
         throw new Error('string argument is not of type string.');
    }

    var str = string.split('');
    var frequencies = {};
    for (var c = 0; c < str.length; c++) {
        var charCode = String.fromCharCode(str[c]);
        if (!frequencies[charCode]) {
            frequencies[charCode] = 1;
        } else {
            frequencies[charCode]++;
        }
    }

    return frequencies;
}

A couple tips: you would want to use a plain object ({}) instead of an array ([]), given that you're counting unique values. Secondly, there's no need to declare the length of an array in Javascript -- arrays are automatically resized as they grow, and the length property is readonly anyway.

4 Comments

I like the insight that your answer gives, however when I run your code everything comes back with a frequency of 1? Also could you elaborate more on why an object should be used over an array in this case. Why would the object be better suited for counting unique values, are there any performance benefits for doing this?
One of the main reasons to use an object is that arrays are generally used as collections, to be added to with push and unshift, and then iterated over with a for loop or the forEach function. An array is therefore thought of as a group of values, each with a sequential index. The way you're doing it, the indices won't necessarily be sequential, and therefore it's impossible to meaningfully iterate over the array. Performance isn't really the issue.
@coderrick Also, there was a small typo in the code -- it should be working now.
This still doesn't work. When I run it it just give me an obj that has 17 keys. I cant see any of the values.
0

You may do as follows;

var s = "Temple University",
 fmap = Array.prototype.reduce.call(s,(p,c) => (p[c] ? p[c]++ : p[c] = 1,p),{});
for(var i in fmap) console.log(i, "shows up", fmap[i],"times.");

We are using an array functor Array.prototype.reduce() over a string by using a Function method .call(). So the first argument passed to .call() is the string s itself (designating the context to be called upon) and a callback ((p,c) => (p[c] ? p[c]++ : p[c] = 1,p)) for the second argument to be invoked per item (character) of the string. The .reduce() functor uses an empty object {} as an initial value which will be assigned to p, whereas c would be assigned to the first character in the first turn. It will generate a map called fmap like;

{ T: 1,
  e: 3,
  m: 1,
  p: 1,
  l: 1,
  ' ': 1,
  U: 1,
  n: 1,
  i: 2,
  v: 1,
  r: 1,
  s: 1,
  t: 1,
  y: 1 }

Then a for in loop traverses over the map keys and we display the obtained data by a console.log() instruction.

1 Comment

Thanks for the nice functional and somewhat monadic solution. However I don't understand the code could you elaborate? What is the significance of using flatmap (I'm green when it comes to functional programming). Also do you know of any good blogs for learning sound functional programming in JavaScript?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.