D3 v4 как синхронно перебирать данные - PullRequest
0 голосов
/ 24 февраля 2020

У меня есть массив с именем states, который является массивом массивов. Каждый элемент массива имеет 2 элемента, имя штата США и его сокращение:

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

У меня есть карта с именем statesData с ключом = сокращение штата. Я пытаюсь использовать массив 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.each и array.forEach являются асинхронными функциями.

В настоящее время я не понимаю, как я могу обойти это: данные должен существовать вне используемой функции statesData.forEach, и к тому времени данные уже не будут существовать.

Я думаю, что есть что-то в асинхронной разработке, которую я упускаю.

Я могу предоставить дополнительную информацию по запросу. Спасибо!

Ответы [ 2 ]

0 голосов
/ 24 февраля 2020

Вы можете легко создать новый объект Map, используемый для сопоставления сокращений состояний с их полными именами, передав новую копию массива states в конструктор Map с обратными ключами и значениями:

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

Служит помощником для разрешения имен состояний при последующем создании новой карты statesFullData из карты statesData:

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.
  )
);

Посмотрите следующий фрагмент рабочей демо-версии :

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);
0 голосов
/ 24 февраля 2020

Полная демонстрация (также ниже): 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);

enter image description here

enter image description here

Шаг за шагом:

Исходные данные:

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. Инвертировать наш массив массивов (может называться массивом трупов на других языках). Мы делаем реверсирование, используя array.map() для перебора внешнего массива и [...child.reverse()] для реверса внутреннего массива:

    const statesReversed = [
      ['AZ', 'Arizona',],
      ['AL', 'Alabama'],
      ['AK', 'Alaska'],
      ['AR', 'Arkansas'],
      ['CA', 'California']
    ];
    
  2. Затем мы можем взять это и использовать его для создания javascript объект (/ ha sh таблица), использующий 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);
    
...