【问题标题】:D3 v4 how to synchronously iterate through dataD3 v4 如何同步迭代数据
【发布时间】:2020-06-07 14:10:10
【问题描述】:

我有一个名为states 的数组,它是一个数组数组。每个数组元素有 2 项,一个美国州名及其缩写:

states = [
  ['Arizona', 'AZ'],
  ['Alabama', 'AL'],
  ['Alaska', 'AK'],
  ['Arkansas', 'AR'],
  ['California', 'CA'],
  ...
  ]

我有一个名为 statesData 的地图,其中 key = state 缩写。我正在尝试使用states 数组创建一个与statesData 具有相同值的新地图,但其键等于该州的全名:

function setStatesFullData(statesFullData, statesData) {
  statesData.each(function(key, value) {
    states.forEach(function(element) {
      if (key == element[1]) {
        statesFullData.set(element[0], value);
      }
    })
  })
  console.log(statesFullData.size());
  return statesFullData;
}


var statesFullData = d3.map();
statesFullData = setStatesFullData(statesFullData, statesData);

输出:

0

这是预期的,因为变量范围和(我相信)map.eacharray.forEach 是异步函数。

我目前不明白如何解决这个问题:数据必须存在于要使用的statesData.forEach 函数之外,到那时数据将不存在。

我认为我缺少一些关于异步开发的东西。

我可以根据要求提供更多信息。谢谢!

【问题讨论】:

    标签: javascript dictionary asynchronous d3.js callback


    【解决方案1】:

    完整演示(也在下方):https://codepen.io/Alexander9111/pen/YzXNGyZ)

    一步一步的解释在这个答案的底部

    const states = [
      ['Arizona', 'AZ'],
      ['Alabama', 'AL'],
      ['Alaska', 'AK'],
      ['Arkansas', 'AR'],
      ['California', 'CA']
    ];
    
    const statesReversed = states.map((child, index) =>{
      return [...child.reverse()]
    });
    
    console.log(statesReversed);
    const statesConversionObject = Object.fromEntries(statesReversed);
    console.log(statesConversionObject);
    
    const statesData = {
      'AZ': ['Some', 'Data'],
      'AL': ['Some', 'Data'],
      'AK': ['Some', 'Data'],
      'AR': ['Some', 'Data'],
      'CA': ['Some', 'Data']
    };
    
    const statesDataModified = {};
    
    for (let key in statesData){
      const newKey = statesConversionObject[key];
      statesDataModified[newKey] = statesData[key];
    }
    
    console.log(statesDataModified);
    const statesFullData = d3.map(statesDataModified);
    console.log(statesFullData);

    一步一步:

    原始数据:

    const states = [
      ['Arizona', 'AZ'],
      ['Alabama', 'AL'],
      ['Alaska', 'AK'],
      ['Arkansas', 'AR'],
      ['California', 'CA']
    ];
    
    const statesData = {
      'AZ': ['Some', 'Data'],
      'AL': ['Some', 'Data'],
      'AK': ['Some', 'Data'],
      'AR': ['Some', 'Data'],
      'CA': ['Some', 'Data']
    };
    
    1. 反转我们的数组数组(在其他语言中可能称为 touples 数组)。我们通过使用array.map() 来迭代外部数组和[...child.reverse()] 来反转内部数组来进行反转:

      const statesReversed = [
        ['AZ', 'Arizona',],
        ['AL', 'Alabama'],
        ['AK', 'Alaska'],
        ['AR', 'Arkansas'],
        ['CA', 'California']
      ];
      
    2. 然后我们可以用它来创建一个javascript对象(/哈希表) 使用Object.fromEntries(statesReversed),这样我们就可以使用它来“查找”缩写并返回全名。我们这样做:

      const statesConversionObject = Object.fromEntries(statesReversed);
      //which gives us:
      statesConversionObject = {
        AK: "Alaska",
        AL: "Alabama",
        AR: "Arkansas",
        AZ: "Arizona",
        CA: "California"
      }
      
    3. 这使我们可以像这样进行查找:

      const statesDataModified = {};
      
      for (let key in statesData){
        const newKey = statesConversionObject[key];
        statesDataModified[newKey] = statesData[key];
      }
      
    4. 我们得到回报:

      statesDataModified = {
        'Arizona': ['Some', 'Data'],
        'Alabama': ['Some', 'Data'],
        'Alaska': ['Some', 'Data'],
        'Arkansas': ['Some', 'Data'],
        'California': ['Some', 'Data']
      };
      
    5. 最后,转换成d3.map()

      const statesFullData = d3.map(statesDataModified);
      

    【讨论】:

      【解决方案2】:

      您可以轻松地创建一个新的 Map 对象,用于将状态的缩写映射到它们的全名,方法是将您的 states 数组的新副本传递给键和值颠倒的 Map 构造函数:

      const statesMap = new Map(states.map(([name, abbr]) => [abbr, name]));
      

      在随后从 statesData 映射创建新的 statesFullData 映射时,这充当解析州名称的助手:

      const statesFullData = new Map(                    // Create new map (full names-to-data) from...
        Array.from(                                      // ...array...
          statesData,                                    // ...from previous map (abbr-to-data)...
          ([abbr, data]) => [statesMap.get(abbr), data]  // ...keys resolved to full name by abbreviation.
        )
      );
      

      查看以下 sn-p 以获取工作演示:

      const states = [
        ['Arizona', 'AZ'],
        ['Alabama', 'AL'],
        ['Alaska', 'AK'],
        ['Arkansas', 'AR'],
        ['California', 'CA'],
      ];
      
      const statesData = new Map([
        ['AZ', "AZ data"],
        ['AL', "AL data"],
        ['AK', "AK data"],
        ['AR', "AR data"],
        ['CA', "CA data"],
      ]);
      
      const statesMap = new Map(states.map(([name, abbr]) => [abbr, name]));
      
      const statesFullData = new Map(
        Array.from(
          statesData,
          ([abbr, data]) => [statesMap.get(abbr), data]
        )
      );
      
      console.log(...statesFullData);

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-04
        • 1970-01-01
        • 1970-01-01
        • 2018-05-23
        • 2015-11-11
        相关资源
        最近更新 更多