2

Context: I am successfully reading a CSV file into an array with d3. The data consists of personal IDs (which occur multiple times) and of one item (out of A, B, C, D, E, F, G) associated with the ID. I want to summarize this data in a histogram-like way: I want to create a 2D associative array, which, for every ID and every item, stores the frequency of the item in all data rows containing the ID. The IDs are not continuous from 0 to n, but rather random numbers, that's why I want to use an associative array for the first dimension, too, rather than a normal array.

The following code works and returns just what I want at the call of console.log(results), at least, when I tap the expand sign.

However, calling console.log(results[0]) does not work, where 0 is an existing key in the results array, as it should be and as I can see in the console.

There are very similar questions on SO, and the answer is to use Object.keys(results) or JSON.stringify(results). But these do not work for me, either (see code).

I am very confused. In Python or Java this would be the easiest thing in the world. Why doesn't it work in JavaScript? And how can I make it work?

var results = {}; 

d3.csv("data.csv", data => {
    data.forEach(row => {
        if (!(row["id"] in results)) {
            results[row["id"]] = {"A": 0, "B": 0,"C": 0, "D": 0, "E": 0, "F": 0, "G": 0};
        }
        results[row["id"]][row["category"]]++;
    });
});

console.log(results); 
// {}
// on expansion:
// 0: {A: 1, B: 5, C: 0, D: 0, E: 0, ...}
// 1: {A: 0, B: 3, C: 0, D: 1, E: 0, ...}
// ...

console.log(results[0]);
// undefined

console.log(results["0"]);
// undefined

console.log(Object.keys(results));
// []
// on expansion:
// length: 0

console.log(JSON.stringify(results));
// {}
// not expandable

Example of data.csv:

id,category
0,A,
0,B,
0,C,
0,C,
0,C,
1,D,
2,D,
2,E,
5,A,
5,B,
5,C,

SOLUTION:

Quentin is right that this is about asynchronicity, however I'd like to point out how I adapted the specific code:

The problem has been: The console.logs are executed before the results are calculated, because forEach() is an asynchronous function and d3.csv() is also an asynchronous function. The console is funny: When I click on the expand button, the results have already been calculated because some seconds have passed.

  • So, I changed the asynchronous forEach function into a normal for loop.
  • As there is no synchronous CSV-function in d3, I put the rest of the data-processing code inside the d3-CSV-callback.

Code:

var results = {}; 

d3.csv("data.csv", data => {
    for (key in Object.keys(data)) {
        row = data[key];
        if (!(row["id"] in results)) {
            results[row["id"]] = {"A": 0, "B": 0,"C": 0, "D": 0, "E": 0, "F": 0, "G": 0};
        }
        results[row["id"]][row["category"]]++;
    }
    console.log(results); 
    // 0: {A: 1, B: 5, C: 0, D: 0, E: 0, ...}
    // 1: {A: 0, B: 3, C: 0, D: 1, E: 0, ...}
    // ...

    console.log(results[0]);
    // {A: 1, B: 5, C: 0, D: 0, E: 0, ...}

    // do all the consequent data processing in here
});
David
  • 513
  • 7
  • 14
  • Could you link an example of the data you iterate through your `data.forEach(row => {` that way we can run the example and debug it. – Nils Kähler Mar 09 '19 at 22:33
  • Syntax error in code: results[row["id"] = { ... } – jarmod Mar 09 '19 at 22:57
  • Are you sure the row number isn't a string? Try `results["0"]` – Christian Vincenzo Traina Mar 09 '19 at 22:59
  • I added some example data and fixed the syntax error (it just emerged when I adapted the code for SO). String "0" is a good idea but still returns undefined :/ – David Mar 09 '19 at 23:04
  • @Quentin Thanks for your suggestion! I reacted to it and inserted the specific solution. Does it make sense to remove the duplicate marking so that I can post it as a real answer, linking to the asynchronicity thread? – David Mar 09 '19 at 23:54
  • What I still do not understand: Why does the console even offer me to expand the array if it is empty at the time when it is logged to the console? It usually does not offer to expand empty arrays! Is there a reason for this behaviour? Is there a place to file an issue about this behaviour? It's so confusing. – David Mar 09 '19 at 23:56
  • 1
    https://stackoverflow.com/questions/17320181/console-log-showing-only-the-updated-version-of-the-object-printed – Quentin Mar 09 '19 at 23:58

0 Answers0