0

I am parsing through a csv file. My goal is to look for the names that starts with "A", "B" and count the occurrences. The problem with the following code is it never completes the while loop.

HTML:

<form>
  <input type="button" id="csv1ButtonRun" value="Run" style="background-color: lightgray"/>
</form>

Scripts included:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="app.js"></script>
<script src="jquery.csv-0.71.js"></script>

JavaScript:

var babyCsv = " Jacob, 1, boy, 2010, Isabella, 1, girl, 2010, Ethan, 2, boy, 2010, Sophia, 2, girl, 2010, Michael, 3, boy, 2010, Emma, 3, girl, 2010, Jayden, 4, boy, 2010, Olivia, 4, girl, 2010, William, 5, boy, 2010, Ava, 5, girl, 2010, Alexander, 6, boy, 2010, Emily, 6, girl, 2010, Noah, 7, boy, 2010, Abigail, 7, girl, 2010, Daniel, 8, boy, 2010, Madison, 8, girl, 2010, Aiden, 9, boy, 2010, Chloe, 9, girl, 2010, Anthony, 10, boy, 2010, Mia, 10, girl, 2010, Joshua, 11, boy, 2010, Addison, 11, girl, 2010, Mason, 12, boy, 2010, Elizabeth, 12, girl, 2010, Christopher, 13, boy, 2010, Ella, 13, girl, 2010, Andrew, 14, boy, 2010, Natalie, 14, girl, 2010, David, 15, boy, 2010, Samantha, 15, girl, 2010, Matthew, 16, boy, 2010";

var data = $.csv.toArray(babyCsv);

$("#csv1ButtonRun").click(function() {

    var arrayLength = data.length / 4;
    var count1 = 0;
    var count2 = 0;
    var i = 0;

    while (i <= arrayLength) {

        var name = data[i * 4];
        if (name.substring(0, 2) == " A") {
            count1 = count1 + 1;
        }
        else if (name.substring(0, 2) == " B") {
            count2 = count2 + 1;
        };
        i++;
    };

    document.write(count1 + count2);
});
Weafs.py
  • 22,731
  • 9
  • 56
  • 78
  • *"it never completes the while loop"* means you have an infinite loop or what? Please describe your problem better. – Felix Kling Aug 14 '14 at 02:53
  • 4
    don't use `document.write`. Use `console.log()` if you want to just see "a result" (it'll log into the dev console. every browser has one), or use DOM building methods (`var div = document.createElement('div'); div.innerHTML = "..."; document.body.appendChild(div)` and their ilk, or jQuery) to get results injected into the page – Mike 'Pomax' Kamermans Aug 14 '14 at 02:54
  • One thing, since you say you're new to javascript, are you actually referencing JQuery? Because if you're not, the whole block around the loop would never run. By referencing, I mean `src="path/tojquery.js"` – zfollette Aug 14 '14 at 02:55
  • 1
    Also make sure that you have a clickable element with the ID of "csv1ButtonRun", otherwise the click event falls on deaf ears. – J.D. Pace Aug 14 '14 at 02:55
  • For this very limited use case, you can use `var matches = babyCsv.match( / [AB]/g ); matches = ( matches ? matches.length ? 0 );` – J.D. Pace Aug 14 '14 at 02:59
  • In addition to J.D. Pace, you can put a try/catch block around the code to notify you of 0 occurrences. – zfollette Aug 14 '14 at 03:00
  • 1
    Or, J.D. Pace can edit his comment and correct the problem. – J.D. Pace Aug 14 '14 at 03:01
  • I'm assuming `name` is supposed to be an element of the csv. there is no code here to extract a `name` element from the `data` – chiliNUT Aug 14 '14 at 03:03

1 Answers1

5

jsFiddle

Your CSV data isn't properly formatted, so your JS object doesn't have any meaningful structure to it. You should separate individual records (rows) in the file with newline characters. Use commas to separate values within a single row. Like:

var babyCsv = " Bryan, 1, boy, 2010 \n Isabella, 1, girl, 2010 \n Bobby, 2, boy, 2010 \n Sophia, 2, girl, 2010 \n Nina, 5, girl, 2010 \n Alexander, 6, boy, 2010 \n Aiden, 9, boy, 2010 \n Anthony, 10, boy, 2010";

Then use the appropriate $.csv.toArrays method to parse the data and return a 2D array of records. Then each entry in your array is for a single child, in the form:

[
    [name1, age1, gender1, year1],
    [name2, age2, gender2, year2],
    ...
];

Finally, in your loop, you must update the value of the name variable each iteration so that you actually do check against each of the children; currently your not changing the value of name between iterations. This is really nicely suited to a for loop. $.trim will also make it easy to get rid of any extra white spaces at the beginnings of strings, though jquery-csv may already do that. So your final code would look like:

var babyCsv = "..."; // your data here

var data = $.csv.toArrays(babyCsv);

$(function () {
    $("#csv1ButtonRun").click(function () {

        var count1 = 0;
        var count2 = 0;

        console.log("Num kids: " + data.length);

        for (var i = 0; i < data.length; i++) {
            var name = $.trim(data[i][0]); //name is first column

            if (name[0] == "A") {
                count1++;
            } else if (name[0] == "B") {
                count2++;
            };
        };

        console.log("Kids with A or B names: " + (count1 + count2));
    });
});
Evan Plaice
  • 13,944
  • 6
  • 76
  • 94
nbrooks
  • 18,126
  • 5
  • 54
  • 66
  • If you do decide to keep your data all in a single row (which I really don't recommend, unless it's coming from an external source you can't control), then you can still use the `for` loop but replace `i++` with `i+=4`. Then, to access the name, you would do `var name = $.trim(data[i])` (without the second index). – nbrooks Aug 14 '14 at 03:35
  • 1
    You can even go one step further with making your CSV text 'correct' by adding column headers. Then you can use `$.csv.toObjects` which will return an array of objects. You can then reference columns by name: `var name = $.trim(data[i].Name);`. [jsFiddle](http://jsfiddle.net/jaxj9a02/1/) – nbrooks Aug 14 '14 at 03:51
  • @chipChocolate.py No problem! If this solved your problem, please [mark the answer as accepted](http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work) (by clicking the faded arrow beside the answer). – nbrooks Aug 14 '14 at 15:27