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

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

本文关键字:对象 属性 单个 何使用 javascript 获取 嵌套      更新时间:2023-09-26

对于一个显示国家数据的交互式地图(使用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年犯罪率的最小值和最大值,是否有一个简单的命令来检索这些信息?

我确实有一个所有可用国家/地区的列表,当然可以循环浏览该列表,获得指定年份的值,将其与全局最小/最大值进行比较,并在必要时进行更改(使用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()来获得关联数组的属性值(静态对象)数组,将嵌套对象嵌套到包含感兴趣的字段值的较小数组中。这些属性值/对象随后被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>