如何使用 javascript 获取嵌套对象中所有子项的单个 属性?

How to get a single property of all children in a nested object using javascript?

对于显示国家/地区随时间变化的数据(使用 d3)的交互式地图,我有一个名为 dataset 的大型对象。 dataset 的属性也是由国家名称标识的对象。下一层是对象,同样由年份表示。最后一层终于是要显示的数据了。 结构是这样的:

dataset
    - CountryA
        - 2010
            - population: 4000000
            - crime rate: 17.4
            - GDP per capita: 2800
        - 2011 
            - population: 4100000
            - crime rate: 16.8
            - GDP per capita: 2900
        - ...
    - CountryB
        - 2010
            - population: 3700000
            - crime rate: 25.6
            - GDP per capita: 1200
        - 2011 
            - population: 3850000
            - crime rate: 27.2
            - GDP per capita: 1180
        - ...
    - ...

现在,为了更新地图,我需要找到特定 属性 的范围,以便调整我想要使用的颜色范围。例如,如果我想获得 2010 年犯罪率的最小值和最大值,是否有简单的命令来检索该信息?

我确实有一个所有可用国家的列表,当然可以遍历该列表并获取指定年份的值,将其与全球 min/max 值进行比较,并在必要时进行更改(使用 Math.min/max).我只是想知道,如果我有一个简单的方法,比如

var crimeRateLow = getGlobalMin(dataset, 2, "crime rate");

// magic function
function getGlobalMin(object, unspecifiedLevels, indicator) { ... }

我目前正在使用以下函数,j 是指标,year 是全局设置变量:

function getRange(j) {
  var jRange = {"min": 0, "max": 0};
  for (k in dataset) {
    jRange["min"] = Math.min(jRange["min"], dataset[k][year][j]);
    jRange["max"] = Math.max(jRange["max"], dataset[k][year][j]);
  }
  return jRange;
}

虽然 d3 中没有内置函数解决您的问题,但 d3 可能有助于优雅地解决它。

  1. 通过将 d3.values() to get an array of property values (still objects) of the associative array. These property values/objects are afterwards mapped 重复应用于仅包含感兴趣的字段值的数组,将嵌套对象取消嵌套到包含感兴趣的字段值的较小数组中。

  2. 使用d3.merge()将这些数组合并为一个大数组。

  3. 应用d3.extent()从中获取全局范围(即数组[min,max])。

    function getGlobalExtent(data, field) {
        return d3.extent(     // (3.) Get the global extent.
            d3.merge(     // (2.) Merge all arrays into a single one.
                d3.values(data)     // (1.) Array of all country objects in dataset
                    .map(function(country) {     // (1.) Map each country to array of field values for all years within.
                            return d3.values(country)     // (1.) Array of years in each country
                                        .map(function(year) {     // (1.) Map each year to the requested field value.
                                            return year[field];
                                        });
                    })
            )
        );
    }
    

我整理了一个工作片段:

var dataset = {
    "CountryA": {
        "2010": {
            "population": 4000000,
            "crime rate": 17.4,
            "GDP per capita": 2800
        },
        "2011": {
            "population": 4100000,
            "crime rate": 16.8,
            "GDP per capita": 2900
        }
    },
    "CountryB": {
        "2010": {
            "population": 3700000,
            "crime rate": 25.6,
            "GDP per capita": 1200
        },
        "2011": {
            "population": 3850000,
            "crime rate": 27.2,
            "GDP per capita": 1180
        }
    }
};

function getGlobalExtent(data, field) {
    return d3.extent(     // (3.) Get the global extent.
        d3.merge(     // (2.) Merge all arrays into a single one.
            d3.values(data)     // (1.) Array of all country objects in dataset
                .map(function(country) {     // (1.) Map each country to array of field values for all years within.
                        return d3.values(country)     // (1.) Array of years in each country
                                    .map(function(year) {     // (1.) Map each year to the requested field value.
                                        return year[field];
                                    });
                })
        )
    );
}

// population: 3700000,4100000
//console.log("population:", getGlobalExtent(dataset, "population").join());

// crime rate: 16.8,27.2
//console.log("crime rate:", getGlobalExtent(dataset, "crime rate").join());

// GDP per capita: 1180,2900
//console.log("GDP per capita:", getGlobalExtent(dataset, "GDP per capita").join());
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>