Home > Mobile >  Unique pairs from data in a drop down select list using d3.js?
Unique pairs from data in a drop down select list using d3.js?

Time:05-31

I'd like to populate a dropdown list (select tag) with only unique values from an object.

This is the object with the data:

[
    {
        "code": 1,
        "abbr": "BR",
        "vote": 49277010
    },
    {
        "code": 1,
        "abbr": "BR",
        "vote": 31342051
    },
    {
        "code": 43,
        "abbr": "RS",
        "vote": 3353623
    },
    {
        "code": 31,
        "abbr": "MG",
        "vote": 3037957
    },
    {
        "code": 31,
        "abbr": "MG",
        "vote": 5017922
    },
    {
        "code": 35,
        "abbr": "SP",
        "vote": 2650440
    },
    {
        "code": 42,
        "abbr": "SC",
        "vote": 2603665
    },
    {
        "code": 1,
        "abbr": "BR",
        "vote": 71347057
    },
    {
        "code": 26,
        "abbr": "PE",
       "vote": 2309104
    }
]

And here is how I get the data to build the dropdown list:

//initialize the dropdown
var dropdown = d3.select("#sel")

dropdown
    .selectAll('myOptions')
    .data(data)
    .enter()
    .append('option')
    .text(function (d) { return d.abbr; }) //text showed in the options
    .attr("value", function (d) { return d.code; }) //values returned by each option

The problem is that repeated values are shown instead of only one for each code/abbr as you can see below:

<select id="sel">
  <option value="1">BR</option>
  <option value="1">BR</option>
  <option value="43">RS</option>
  <option value="31">MG</option>
  <option value="31">MG</option>
  <option value="35">SP</option>
  <option value="42">SC</option>
  <option value="1">BR</option>
  <option value="26">PE</option>
</select>

How can I filter the data to have only unique values in the options instead?

<select id="sel">
  <option value="1">BR</option>
  <option value="43">RS</option>
  <option value="31">MG</option>
  <option value="35">SP</option>
  <option value="42">SC</option>
  <option value="26">PE</option>
</select>

== EDIT ==

I was able to get uniques using set just like the following:

const selectedData = [... new Set(data.map(d => d.abbr))].sort();

But then I can work only with abbr. How could I get code too?

Tried [... new Set(data.map(d => [d.abbr, d.code))], but without success, as this creates an object of arrays with all unfiltered data again.

CodePudding user response:

New in d3 v7 is flatGroup which will return an array with the unique pairs of code and abbr plus the associated array objects:

d3.flatGroup(data, d => d.code, d => d.abbr);

If you're using an earlier version, then you can use a Map to get a similar result (but without the associated array objects):

const uniqueData = Array.from(
  data.reduce((a, c) => {
    a.set(c.code, c.abbr);
    return a;
  }, new Map())
);

console.log(uniqueData);

The working example below uses flatGroup:

const uniqueData = d3.flatGroup(data, d => d.code, d => d.abbr);

console.log(uniqueData);

//initialize the dropdown
var dropdown = d3.select("#sel")

dropdown
  .selectAll('myOptions')
  .data(uniqueData)
  .enter()
  .append('option')
  .text(function (d) { return d[1]; }) //text showed in the options
  .attr("value", function (d) { return d[0]; }) //values returned by
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.3.0/d3.min.js"></script>
<select id="sel">
</select>
<script>
const data = [
    {
        "code": 1,
        "abbr": "BR",
        "vote": 49277010
    },
    {
        "code": 1,
        "abbr": "BR",
        "vote": 31342051
    },
    {
        "code": 43,
        "abbr": "RS",
        "vote": 3353623
    },
    {
        "code": 31,
        "abbr": "MG",
        "vote": 3037957
    },
    {
        "code": 31,
        "abbr": "MG",
        "vote": 5017922
    },
    {
        "code": 35,
        "abbr": "SP",
        "vote": 2650440
    },
    {
        "code": 42,
        "abbr": "SC",
        "vote": 2603665
    },
    {
        "code": 1,
        "abbr": "BR",
        "vote": 71347057
    },
    {
        "code": 26,
        "abbr": "PE",
       "vote": 2309104
    }
];
</script>

  • Related