D3@6 Generic direction on addressing Map data structures in arrow functions

Viewed 52

Have an Observable using D3 v6 and am starting to use the Map data structure. While it seems array-based I am having difficulty translating how to get to different parts of maps in arrow functions.

I have a data set shaped:

dataByHub = Map(2) {
  "ST" => Array(19) [Object, Object, Object... ]
  "FING" => Array(27) [Object, Object, Object ...]

A log of the data going into the function to generate the path looks like:

data 
Pn {_groups: Array(2), _parents: Array(2)}
_groups: (2) [Array(19), Array(27)]
_parents: (2) [g#ST.hub, g#FING.hub]
__proto__: Object

...and, for each hub (_parents which determines my y_hub), I want to iterate over the appropriate Array (_group) and pass in the sets of Xs to a function to create a path. The result should be a line with variable length spaces and dashes representing disconnection events.

What I have...

The D3 portion looks like, where I want to attach the Xs from a hub to a path:

  d3.select("#hubs").selectAll(".hub")
    .data(dataByHub) 
    .enter().append("g")
    .attr("class", "hub")
    .attr("id", d => d[0])
    .selectAll("path")
    .data((d,i) => d[1])
    .join("path")
      .call(log,"data")
      .style("stroke", "black")
      .style("fill", "none")
      .attr("d", (d,i) => segment(d.Xs,i))

Which uses segment() to generate the path:

function segment(data, hub) {
  const p = d3.path();
  console.log("segment", data); //data.Xs[0]
  const y_hub = hub * 100;
  p.moveTo(data.Xs[0],y_hub);
  p.lineTo(data.Xs[1],y_hub);
  p.closePath();
  // console.log("p", p);
  return p.toString();
}

I have tried different setups for the .data for the path but either get undefined or an individual pair of Xs's instead of a series of them.

1 Answers

Based on @Robin Mackenzie's question about passing an array or individual pair I refactored the function to accept the array.

So the call became:

.attr("d", (d,i) => events(d[1]) )

However, the important part of the solution was how to get to the elements of the Map. The missing piece was the index into the array after "data" before ".Xs"

function events(data) {
  const p = d3.path();
  const y_hub = yScale(data[0].Hub);
  for (var n=0; n < data.length; n++) {
    p.moveTo(xScale(data[n].Xs[0]),y_hub);
    p.lineTo(xScale(data[n].Xs[1]),y_hub);
    }
  p.closePath();
  return p.toString();
}

Thanks to my friend Alex Carroll for additional help on Maps.

Related