1

Suppose I have the following dc.js objects:

var chart_11   = dc.barChart("#chart-11"),
    chart_12   = dc.barChart("#chart-12"),
    chart_13   = dc.barChart("#chart-13"),
    chart_21   = dc.barChart("#chart-21"),
    chart_22   = dc.barChart("#chart-22"),
    chart_23   = dc.barChart("#chart-23");

Next, I read in some data and do some stuff with that data:

d3.csv("../data/test_data.csv").then(function(data) {

    var var_names = ["x", "y", "z", "a", "b", "c"];

    var ndx = crossfilter(data),
        chart_11_dim = ndx.dimension(function(d) { return +d[var_names[0]]; }),
        chart_12_dim = ndx.dimension(function(d) { return +d[var_names[1]]; }),
        chart_13_dim = ndx.dimension(function(d) { return +d[var_names[2]]; }),
        chart_21_dim = ndx.dimension(function(d) { return +d[var_names[3]]; }),
        chart_22_dim = ndx.dimension(function(d) { return +d[var_names[4]]; }),
        chart_23_dim = ndx.dimension(function(d) { return +d[var_names[5]]; });

    var chart_11_min = +chart_11_dim.bottom(1)[0][var_names[0]],
        chart_11_max = +chart_11_dim.top(1)[0][var_names[0]],
        chart_12_min = +chart_12_dim.bottom(1)[0][var_names[1]],
        chart_12_max = +chart_12_dim.top(1)[0][var_names[1]],
        chart_13_min = +chart_13_dim.bottom(1)[0][var_names[2]],
        chart_13_max = +chart_13_dim.top(1)[0][var_names[2]],
        chart_21_min = +chart_21_dim.bottom(1)[0][var_names[3]],
        chart_21_max = +chart_21_dim.top(1)[0][var_names[3]],
        chart_22_min = +chart_22_dim.bottom(1)[0][var_names[4]],
        chart_22_max = +chart_22_dim.top(1)[0][var_names[4]],
        chart_23_min = +chart_23_dim.bottom(1)[0][var_names[5]],
        chart_23_max = +chart_23_dim.top(1)[0][var_names[5]];

});

While this works, it's not very dry nor is it easy to maintain scale. I know there has to be a better way to dynamically create these variables, but I'm not confident on which approach (e.g. loops, maps, reduce) are likely to scale the best. I do not code frequently in javascript, so I am hoping someone more experienced can point me in the right direction.

JasonAizkalns
  • 20,243
  • 8
  • 57
  • 116
  • where/how do you use the variables later? – Nina Scholz Mar 07 '19 at 20:09
  • 1
    If you need multiple similar variables, don't create them in the global scope, store them in an `Array`. eg. `const charts =[]; for(let i = 1; i < 3; ++i) chart[i] = db.barChart(\`#chart-${i}\`);` After you have this array it should be easy to deduce the rest of the DRY coding. – XCS Mar 07 '19 at 20:09
  • 1
    If your variable needs a number, it probably shouldn't be a variable. – Kevin B Mar 07 '19 at 20:10
  • 1
    @KevinB Unless it's math: `x1, y1, x2, y2` :D – XCS Mar 07 '19 at 20:11
  • nah, `x = [1,2]` – Kevin B Mar 07 '19 at 20:12
  • @NinaScholz these are later used to draw the actual dc.js chart objects: for example: `chart_11 .dimension(chart_11_dim) .group(chart_11_grp) .round(dc.round.floor) .alwaysUseRounding(true) .x(d3.scaleLinear().domain([chart_11_min - ((chart_11_max - chart_11_min) * breathing_room), chart_11_max + ((chart_11_max - chart_11_min) * breathing_room)])) .xUnits(function(start, end, xDomain) { return (end - start) / c11_bin; });` – JasonAizkalns Mar 07 '19 at 20:12
  • It's very common in high performance apps (games) to use multiple variables instead of an Object/Array in order to speed-up memory access and reduce garbage created. But I do agree and love your initial statement :D – XCS Mar 07 '19 at 20:13
  • 1
    I think this kind of questions are more related to a [**Code Review**](https://codereview.stackexchange.com/) – jherax Mar 07 '19 at 23:52
  • 1
    And related to the question itself, you can opt for holding all those variables as properties of an object created dynamically. Check this [answer](https://stackoverflow.com/a/19837961/2247494) for _"Creating object with dynamic keys"._ After the object has been created you can navigate thought its properties with a `for...in` loop or with `Object.keys(...).forEach(...)` – jherax Mar 07 '19 at 23:55
  • 1
    @jherax thank you -- I debated code review; perhaps I'll move it there. – JasonAizkalns Mar 08 '19 at 00:03
  • I bet you could clean this up with some judicious use of functions, e.g. make a function that creates a dimension and group and initializes the chart. – Gordon Mar 08 '19 at 19:34
  • @Gordon - thanks, I moved this to [`Code Review`](https://codereview.stackexchange.com/q/215041/48977) with a more complete example. – JasonAizkalns Mar 08 '19 at 20:17

1 Answers1

1

You can create a helper file to export the variables as a javascript module.

So in your module file named "data.js" you could have:

export const chart11   = dc.barChart("#chart-11"),
    chart12   = dc.barChart("#chart-12"),
    chart13   = dc.barChart("#chart-13"),
    chart21   = dc.barChart("#chart-21"),
    chart22   = dc.barChart("#chart-22"),
    chart23   = dc.barChart("#chart-23");

Then wherever you need to reference the data in someotherfile.js you could use:

import {chart11, chart12, chart13, chart21, chart22, chart23} from '../data';

const chart11Min = chart11...

Idk if you work in node at all, but this is the module pattern used throughout the node environment. This allows a single module declaration and as many import references to that module as needed. Side note, recommend using const for constant variables and let for dynamic variables. The var keyword is not best practice due to its lack of differentiation.

Len Joseph
  • 1,406
  • 10
  • 21