'what is the equivalent group code for nest and group functions in D3 V6

I am absolute new to both JavaScript and D3. I have problem to convert below D3 codes from version 3 to 6 .
data:
d2.csv:

city,type,price,id
a,c,10,1
a,c,15,2
a,d,30,3
a,d,40,4
a,e,5,5
a,e,10,6
a,e,7,7
b,c,15,8
b,c,20,9
b,d,9,10
b,d,4,11
b,e,12,12
b,e,15,13

D3 V3 code:

data = d3.csv('./data/d2.csv', function (data) {
    var nestedData = d3.nest()
        .key(function (d) { return d.city; }).sortKeys(d3.descending)
        .key(function (d) { return d.type; }).sortKeys(d3.ascending)
        .sortValues(function (a, b) { return +b.price - +a.price; })
        .entries(data);
    console.log(nestedData);

})

please help me with version 6



Solution 1:[1]

You can use the logic of the little helper function in this answer to convert the nested Map returned from d3.group back into an Object with the format you expect per d3.nest. This should work for any level of nesting.

To accommodate the sorting logic, use d3.ascending and d3.descending over the array of objects you get from your CSV before you call d3.group.

Working example:

const csv = `city,type,price,id
a,c,10,1
a,c,15,2
a,d,30,3
a,d,40,4
a,e,5,5
a,e,10,6
a,e,7,7
b,c,15,8
b,c,20,9
b,d,9,10
b,d,4,11
b,e,12,12
b,e,15,13`;

// helper function to convert nested Map to {key: x, values: []} format
const mapToObject = (map = new Map) => Array.from(
  map.entries(), 
  ([k, v]) => ({
    "key": k,
    "values": v instanceof Map ? mapToObject(v) : v
  })
);

// get the data and apply the sorting logic
const data = d3.csvParse(csv)
  .sort((a, b) => d3.descending(a.city, b.city)
    || d3.ascending(a.type, b.type)
    || d3.descending(+a.price, +b.price));

// call the helper function with output of d3.group
const nestedData = mapToObject(
  d3.group(
    data,
    d => d.city,
    d => d.type
  )
);

// same result as your d3.nest example
console.log(nestedData);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>

Solution 2:[2]

Apparently, there is no direct equivalent for d3.nest in V6. I tried d3.group / d3.groups / d3.rollup but did not get exactly the same result...

Instead, you can use the following code:

d3.csv('./data/d2.csv', function (data) {
  const nestedData = data
    .sort((a, b) => {
      if (a.city > b.city) return -1;
      if (a.city < b.city) return 1;
      if(a.type > b.type) return 1; 
      if(a.type < b.type) return -1; 
      return b.price - a.price;
    })
    .reduce((arr, item) => {
      const cityObj = arr.find(({key}) => key === item.city);
      if (!cityObj) {
        arr.push({key: item.city, values: [{key: item.type, values: [item]}]});
        return arr;
      }
      const typeObj = cityObj.values.find(({key}) => key === item.type);
      if (!typeObj) {
        cityObj.values.push({key: item.type, values: [item]});
        return arr;
      }
      typeObj.values.push(item);
      return arr;
    }, []);

  console.log(nestedData);
});

Here is my fiddle with a tested code.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Robin Mackenzie
Solution 2 Michael Rovinsky