0

I am creating a list of words from a String. I then split that string into individual words, gather a count of how many times each word is repeated, and display it. Everything there works perfectly. However, the result displays the words and counts in no specific order. I will want to display them with the highest number first. I have generated the following code:

<!DOCTYPE html>
<html>
<body>

<p>Click the button to display the array values after the split.</p>

<button onclick="analyze()">Analyze</button>

<p id="displayText"></p>

<script>
function analyze() {
    var str = "This this is is is is is is is is is is is is is is is just just a test test test";
    var res = str.split(" ");
    document.getElementById("displayText").innerHTML = res;
    document.getElementById("displayText").innerHTML += "<br/><br/>The amount of words is: " + res.length + "<br/><br/><br/>";

    document.getElementById("displayText").innerHTML += "The list of words:<br/><br/>";

    var words = [];

    var wordsWithCount = [];

    for (i = 0; i < res.length; i++) {
        words.push(res[i]);
        document.getElementById("displayText").innerHTML += words[i] + "<br/><br/>";
    }

    var current = null;
    var cnt = 0;
    for (var i = 0; i < words.length; i++) {
        if (words[i] != current) {
            if (cnt > 0) {
                document.getElementById("displayText").innerHTML += "<br/><br/>" + cnt + " - " + current + "<br/>";
                wordsWithCount.push(cnt + " - " + current);
            }
            current = words[i];
            cnt = 1;
        } else {
            cnt++;
        }
    }

    if (cnt > 0) {
        document.getElementById("displayText").innerHTML += "<br/><br/>" + cnt + " - " + current + "<br/>";
        wordsWithCount.push(cnt + " - " + current);
    }

    wordsWithCount.sort();

    document.getElementById("displayText").innerHTML += "<br/><br/><br/><br/><br/>The list of SORTED words:<br/><br/>";

    for (i = 0; i < wordsWithCount.length; i++) {
        document.getElementById("displayText").innerHTML += wordsWithCount[i] + "<br/><br/>";
    }
}
</script>

</body>
</html>

This is the last bit of the output. As you can see, it's being sorted, but only by first digit. Thus, 15 is displayed before 2. Any thoughts?

The list of SORTED words:

1 - This

1 - a

1 - this

15 - is

2 - just

3 - test

I will most likely need to break this into two arrays at some point, because I will want the user to be able to copy and paste all of the words, without the numbers. However, I assume that will need to be the last step, because if I break the frequency of each word into it's own array of numbers, and keep the words in their own array, then the sort function will sort one array, and the other array will not follow.

4
  • 2
    parseInt() doesn't care if there's non-numeric text after a number at the start of a string. Commented May 10, 2017 at 20:33
  • @Pointy, can you clarify your answer for me a bit? Are you saying I can use parseInt() somewhere in my code to make it do what I'm looking for? Can you provide me with an example of how I can use that? Commented May 10, 2017 at 20:35
  • stackoverflow.com/questions/15478954/… Commented May 10, 2017 at 20:49
  • @Ryan Hope my solution helped. If so, please consider marking my answer as a correct solution. Commented May 11, 2017 at 4:17

3 Answers 3

1

Using a parseInt() method and the solution found here (How to sort an array of integers correctly) to the mix it works!

replace wordsWithCount.sort(); with:

function sortNumber(a,b) {
      return parseInt(a) - parseInt(b);
}

wordsWithCount.sort(sortNumber);

Live here: https://www.w3schools.com/code/tryit.asp?filename=FFGXRIN0VZWO

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

1 Comment

... and swap the order of a and b if you want largest-to-smallest.
1

Do it using Intl.Collator. Like this:

var collator = new Intl.Collator(undefined, {numeric: true, sensitivity: 'base'});
var test = ['1 - this', '3 - this', '14 - this'];
test.sort(collator.compare);

Outputs ["1 - this", "3 - this", "14 - this"]

var collator = new Intl.Collator(undefined, {numeric: true, sensitivity: 'base'});
    var test = ['1 - this', '3 - this', '14 - this'];
    console.log(test.sort(collator.compare));

Comments

0

You can just add a custom compare function to pass into your wordsWithCount.sort() call. Here I declared a function called compareWordCount and used the sugfested method by @Pointy; using parseInt to ignore all non integer parts appended to array value. Take a look at this working snippet:

<!DOCTYPE html>
<html>
<body>

<p>Click the button to display the array values after the split.</p>

<button onclick="analyze()">Analyze</button>

<p id="displayText"></p>

<script>
function compareWordCount(a,b) {
  if (parseInt(a) < parseInt(b))
    return -1;
  return 1;
}

function analyze() {
    var str = "This this is is is is is is is is is is is is is is is just just a test test test";
    var res = str.split(" ");
    document.getElementById("displayText").innerHTML = res;
    document.getElementById("displayText").innerHTML += "<br/><br/>The amount of words is: " + res.length + "<br/><br/><br/>";

    document.getElementById("displayText").innerHTML += "The list of words:<br/><br/>";

    var words = [];

    var wordsWithCount = [];

    for (i = 0; i < res.length; i++) {
        words.push(res[i]);
        document.getElementById("displayText").innerHTML += words[i] + "<br/><br/>";
    }

    var current = null;
    var cnt = 0;
    for (var i = 0; i < words.length; i++) {
        if (words[i] != current) {
            if (cnt > 0) {
                document.getElementById("displayText").innerHTML += "<br/><br/>" + cnt + " - " + current + "<br/>";
                wordsWithCount.push(cnt + " - " + current);
            }
            current = words[i];
            cnt = 1;
        } else {
            cnt++;
        }
    }

    if (cnt > 0) {
        document.getElementById("displayText").innerHTML += "<br/><br/>" + cnt + " - " + current + "<br/>";
        wordsWithCount.push(cnt + " - " + current);
    }

    wordsWithCount.sort(compareWordCount);

    document.getElementById("displayText").innerHTML += "<br/><br/><br/><br/><br/>The list of SORTED words:<br/><br/>";

    for (i = 0; i < wordsWithCount.length; i++) {
        document.getElementById("displayText").innerHTML += wordsWithCount[i] + "<br/><br/>";
    }
}
</script>

</body>
</html>

1 Comment

Your comparator function is incorrect in the case the two numbers are the same. In that case, the function should return 0 not 1, and yes it definitely matters.

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.