Looking up another array from d3 joined data

I need to lookup a value in another array based on a key within the data joined to svg within d3.

The d3 joined dataset is boundaries (which contains a key of lad17cd for the local authority) and then I need to look up the population in localAuthorities using the same key.

I’ve tried various ways (using find on local authorities and the [] notation to refer to a key, but for that, I’m not sure how it would know which field is the key), but none seem to work.

Full code is at Carbon Calculator Map / Chris Woods / Observable, with the lookup code towards the bottom of leafletBoundaryMap.

The currently uncommented line refers to a specific value of lad17cd and this works, but obviously I don’t want to hard code it.

Any pointers warmly welcomed.

const areaPaths = g.selectAll('path')
    .data(boundaries.features)
    .enter()
    .append('path')
    //.attr("fill", d => localAuthorities[d.properties.lad17cd].population > 100000 ? "#ffe26d" : "#c837ed")
    .attr("fill", localAuthorities.find(d => d.lad17cd === "E06000013").population < 100000 ? "#ffe26d" : "#c837ed")
    //.attr("fill", d => localAuthorities.find(la => la.lad17cd === d.properties.lad17cd).population < 100000 ? "#ffe26d" : "#c837ed")

I made a localIndex object from the from localAuthorities data.
That lets me reference the array of localAuthorities using the key from d.properties.lad17cd

localIndex = {
  let idx = {}
  let idxlo = localAuthorities.map(d => d.lad17cd)
  for (let i = 0; i < idxlo.length; ++i) {
   idx[idxlo[i]]= i
  }
  return idx
}
    .attr("fill", d =>  localAuthorities[localIndex[d.properties.lad17cd]].population > 100000 ? "#ffe26d" : "#c837ed")

That shows now show a bug because d.properties.lad17cd is trying to find these data points and they are not present in localAuthorities

S12000005,S12000006,S12000008,S12000010,S12000011,S12000013,S12000014,S12000015,S12000017,S12000018,S12000019,S12000020,S12000021,S12000023,S12000024,
S12000026,S12000027,S12000028,S12000029,S12000030,S12000033,S12000034,S12000035,S12000036,S12000038,S12000039,S12000040,S12000041,S12000042,S12000044,
S12000045,S12000046,W06000001,W06000002,W06000003,W06000004,W06000005,W06000006,W06000008,W06000009,W06000010,W06000011,W06000012,W06000013,W06000014,
W06000015,W06000016,W06000018,W06000019,W06000020,W06000021,W06000022,W06000023,W06000024

You may want to use a Map for that:

lad17cd = new Map(localAuthorities.map(d => [d.lad17cd, d]))
lad17cd.get(d.properties.lad17cd).population
1 Like

Thanks @hellonearthis and @mootari. @mootari, am I right in thinking the map creates a new array of key value pairs, with the value being the whole object from the original array? And that you do this as the lookup only works with key value pairs?

@ChrisWoodsSays While the keys in a Map can be arbitrary things, they only work for 1:1 relationships (in case of duplicate keys only the last entry is kept). If you want to create indexes for non-unique keys, I recommend taking a look at d3.group and d3.rollup.

2 Likes