Ускорьте код javascript для преобразования csv в geojson

Я использую сценарий, который преобразует файл CSV в GeoJSON, чтобы отобразить его на карте. Вы можете убедиться в этом сами здесь. CSV содержит около четырех тысяч строк. Это довольно медленно. Мне интересно, что его замедляет и как я могу его ускорить.

function latLonColumnsToNumbers(data, latName, lonName) {
  return data.map(function(item) {
    if (item.hasOwnProperty(latName)) {
         item[latName] = parseFloat(item[latName]);
         if (isNaN(item[latName])) { //check if row has blank lat/long, and if so, flag it
            var latFlag = 1;
         } else {
             latFlag = 0;
         }
      }
    if (item.hasOwnProperty(lonName)) {
         item[lonName] = parseFloat(item[lonName]);
         if (isNaN(item[lonName])) {
             var lonFlag = 1;
         } else {
             lonFlag = 0;
         }
    }
    if (latFlag == 1 || lonFlag == 1) { //if row has no lat/long, then assign it to the approximate center of the map
        item[latName] = 42.2; 
        item[lonName] = ~83.6;
        return item;            
     }  
    else {
        return item;
    }
  });

Я знаю, что более быстрый способ сделать это — превратить CSV в базу данных sql и вызвать ее с помощью PHP, но это предполагает использование множества серверных вещей, таких как NodeJS, Ajax и т. Д., С которыми я (пока) не знаком. . Поэтому я хотел бы продолжать использовать CSV, пока не научусь, как это делать.

2 ответа
2

Из небольшого обзора;

  • Старая школа for петли все еще бьют map

  • Предотвратить повторный объект[string] доступ, например, доступ несколько раз item[latName], потому что это относительно медленно

  • Обязательно ли создавать новый объект? У меня есть подозрение, что модификация объекта будет быстрее. (Да, не очень хорошая практика, но вы ищете скорости, вам стоит попробовать это)

  • Еще одна вещь, я не решился упомянуть об этом, но оператор плюс может быть быстрее, чем parseFloat согласно jsperf. Так что ты мог просто пойти на

      const newLat = +item[latName];
      const newLong = +item[longName];
    

дайте нам знать;)

Это мое встречное предложение с конверсией места;

function convertLocationToNumbers(data, latName, longName) {
  const dataLength = data.length;
  for(let i = 0; i < dataLength; i++){
    const item = data[i];
    //Dont check for hasownproperty, just go!
    const newLat = +item[latName];
    const newLong = +item[longName];
    if(isNaN(newLat) || isNaN(newLong ){
      item[latName] = 42.2; 
      item[lonName] = ~83.6;
    }else{
      item[latName] = newLat; 
      item[lonName] = newLong;
    } 
  }
}

    Самая медленная часть, вероятно, parseFloats, но я не могу придумать более быстрого способа.

    Одна вещь, которая меня выделяет, — это использование map, но в то же время вы изменяете элементы, поэтому в итоге у вас есть два массива с одинаковым содержимым. Вероятно, вы можете сэкономить время, просто сохраняя тот же массив, используя forEach (или нормальный for цикл, который, вероятно, даже быстрее).

    Также с использованием глобальных переменных (var) и целые числа, в которых можно использовать логическое значение, не помогут. Я также не вижу необходимости в hasOwnProperty.

    В чем смысл ~83.6 (что равно -84)?

    Я бы упростил все это до:

    function latLonColumnsToNumbers(data, latName, lonName) {
        data.forEach(item => {
           item[latName] = parseFloat(item[latName]);
           item[lonName] = parseFloat(item[lonName]);
           
           if (isNaN(item[latName]) || isNaN(item[lonName])) { 
              item[latName] = 42.2; 
              item[lonName] = ~83.6; // or just -84
           } 
        });
    
        // The return isn't needed either. Just use the original array after calling the function.
        return data;
    }
    

      Добавить комментарий

      Ваш адрес email не будет опубликован. Обязательные поля помечены *