Я использую сценарий, который преобразует файл 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 ответа
Из небольшого обзора;
Старая школа
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;
}
