0

I'm working on a visualization in D3 and I'm still in the learning process (JS included) and I want to remove the duplicated code from maxExportYears and maxImportYears.

function calcMaximum(json) {

   let maxExportYears = json.map(function (obj) {
      let maxByYear = [];
      obj.entries.map( function(entry) {
          maxByYear.push(parseFloat(entry.exported));
      });
      return d3.max(maxByYear, function(d) { return d; });
   });

  /// calculate the maximum Export across all years
  let maxExport = d3.max(maxExportYears, function(d) {return d;} );

  /// calculate the maximum Import on each year
  let maxImportYears = json.map(function (obj) {
      let maxByYear = [];
      obj.entries.map( function(entry) {
          maxByYear.push(parseFloat(entry.imported));
      });
      return d3.max(maxByYear, function(d) { return d; });
  });

  /// calculate the maximum Import across all years
  let maxImport = d3.max(maxImportYears, function(d) {return d;} );


  /// calculate the maximum between maxExport and maxImport
  let maximum = d3.max([maxExport, maxImport], function(d) {return d;});
  return maximum;
}

 d3.json('/file_name.json', function(error, json) {
    if (error) throw error;
    let data = json;

    let maximum =  calcMaximum(data);
    let scaleRadius = d3.scaleSqrt().domain([0, maximum]).range([0,150]); 
}

I have created the following function to replace the duplicated code:

function calculateMaxByYear(json, activity) {
  json.map(function (obj) {
    let maxByYear = [];
      obj.entries.map( function(entry) {
        maxByYear.push(parseFloat(entry[activity]));
      })
      let maximus = d3.max(maxByYear, function(d) { return d; });
    return maximus;
  })
};

which in a synchronous way might be called calculateMaxByYear(json, 'imported'); calculateMaxByYear(json, 'exported');, but I don't know how to use it in an asynchronous way.

Any ideas on how to solve this are very welcomed!

Thanks a lot!

Emanuela Ianc
  • 77
  • 1
  • 6
  • What does this have to do with async? I don't see it. Aren't you just going to do `let maxExportYears = calculateMaxByYear(json, 'exported');` ? – Felix Kling Oct 20 '17 at 17:17
  • `d3.json` is asynchronous, `let maxExportYears = calculateMaxByYear(json, 'exported');` returns `undefined` – Emanuela Ianc Oct 20 '17 at 18:47
  • Sure, but not the function you created. – Felix Kling Oct 20 '17 at 18:48
  • So the code from `calcMaximum` works, the only thing I want to do is to refactor it so I don't have duplicated code, and I don't know how to do that. I thought that creating a function like `calculateMaxByYear` might help, but I don't know how to make it work. – Emanuela Ianc Oct 20 '17 at 18:55

1 Answers1

1

Either you think the problem is more complicated than it is, or I am misunderstanding the issue.

First of all you need to fix your function to return the result of the .map operation:

function calculateMaxByYear(json, activity) {
    return json.map(...);
//  ^^^^^^
}

And then you simply replace the existing code with a call to this function:

function calcMaximum(json) {

  let maxExportYears = calculateMaxByYear(json, 'exported');
  // call function     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  let maxExport = d3.max(maxExportYears, function(d) {return d;} );
  let maxImportYears = calculateMaxByYear(json, 'imported');
  // call function     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  let maxImport = d3.max(maxImportYears, function(d) {return d;} );
  let maximum = d3.max([maxExport, maxImport], function(d) {return d;});

  return maximum;
}

However, the whole can be simplified to

function calcMaximum(json) {
  return d3.max(
    calculateMaxByYear(json, 'exported')
      .concat(calculateMaxByYear(json, 'imported'))
  );
}

There is no need for all this intermediate values and there is no need to pass a callback to d3.max. The identify function is basically the default callback.


As I said in my comments, the fact that d3.json is asynchronous has no impact on how calculateMaxByYear is called.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • Thank you so much, returning the result from the map function solved the issue. And yeah, I think I overcomplicated the solution in my head. – Emanuela Ianc Oct 21 '17 at 12:18