2016-02-22 2 views
1

Я знаю процесс создания файла CSV, поэтому мой вопрос более специфичен для данных, которые у меня есть. У меня есть некоторые рекордеры, и у каждого из них есть некоторые данные. Каждая информация состоит из значения и временной метки. Так записывающее выглядит следующим образом:Создание CSV с разнообразными и большими данными

'recorder_name': { 
    samples: [{v: 19, t: new Date()}] 
} 

Проблема заключается в том, что не все регистраторы имеют значения для всех меток времени, и они не имеют одинаковый объем данных. Я начал играть с lodash, но он очень медленный. То, что я до сих пор является следующее:

function createCSVRows(data) { 
    const timestamps = []; 
    const csvRows = []; 

    //data contains all recorders 
    _.forEach(data, ({samples}) => { 
     _.forEach(samples, s => { 
      const timestamp = moment(s.t).utc(); 
      timestamps.push(timestamp.format('YYYY-MM-DD HH:mm:ss')); 
     }); 
    }); 

    _(timestamps) 
     .uniq() 
     .sortBy(t => moment(t).utc()) 
     .forEach(t => { 
      const csvRow = [t]; 

      _.forEach(data, ({samples}) => { 
       const value = _.find(samples, s => moment(s.t).utc().format('YYYY-MM-DD HH:mm:ss') === t); 

       if(!value) { 
        csvRow.push(''); 
       } else { 
        csvRow.push(value.v); 
       } 
      }); 
      csvRows.push(csvRow); 
     }) 
     .value(); 

    return csvRows; 
} 

Итак, я стараюсь, чтобы получить все доступные временные метки, а затем сохранить только уникальные. Проблема заключается в том, как вывести значение для каждой отметки времени. Функция find - это то, что занимает много времени, поскольку каждый рекордер имеет в среднем 500-600 точек данных. Я никогда не видел, чтобы функция выполнялась до конца, так как вкладка браузера умирает через короткое время.

Благодаря

EDIT: В соответствии с комментарием @charlietfl «ы Я также попытался следующие:

_.forEach(data, ({samples}) => { 
    _.forEach(samples, s => { 
     const timestamp = moment(s.t).utc().format('YYYY-MM-DD HH:mm:ss'); 
     if(!timestamps[timestamp]) { 
      timestamps[timestamp] = []; 
     } 

     _.forEach(timestamps, (v, t) => { 
      if(t === timestamp) { 
       v.push(s.v); 
      } else { 
       v.push(''); 
      } 
     }); 
    }); 
}); 

Проблема снова в том, что я должен перебрать меток времени, потому что у меня есть для заполнения всех остальных временных меток пустыми значениями. Закладка все еще умирает. Есть идеи?

EDIT 2: Образец данных:

{ 
    'recorder_a': { 
     samples: [{t: new Date(2015,02,03), v: 10}, {t: new Date(2015,02,04), v: 15}] 
    }, 
    'recorder_b': { 
     samples: [{t: new Date(2015,02,03), v: 11}] 
    } 
} 

и ожидаемый CSV должен выглядеть следующим образом:

Date   recorder_a recorder_b 
2015-02-03  10   11 
2015-02-04  15    - 

Я имею в виду, что если записывающее устройство не имеет значение для метки времени, тогда я должен показать пустую оболочку.

+0

Более эффективный для создания объекта, где временные метки ключи. Итерации один раз и проверить, существует ли ключ или нет. Затем переместите объект обратно в массив. Удалит поиск повторяющегося массива, который 'find()' делает – charlietfl

+0

@charlietfl, вы имеете в виду вместо добавления временных меток в массив? – XeniaSis

+0

Вы могли бы представить небольшой пример? – XeniaSis

ответ

1

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

// object to store dates as keys 
var dates = {} // {'2015-12-22':{recorder_a:4, recorder_c:7}} 
// array of recorder names 
var recorders = Object.keys(data); 
// populate dates object with known recorders per date 
recorders.forEach(function(recorder) { 
    data[recorder].samples.forEach(function(sample) { 
    var dateStr = getDateString(sample.t) 
    if (!dates[dateStr]) { 
     dates[dateStr] = {} 
    } 
    dates[dateStr][recorder] = sample.v 
    }); 
}); 
// array of date keys sorted 
var datesArr = Object.keys(dates).sort(function(a, b) { 
    return new Date(a) - new Date(b); 
}); 

var headings= ['Date'].concat(recorders); 
// now fill in missing recorders on each date 
var res = [csvRow(headings)]; 
datesArr.forEach(function(date) { 
    var row = [date], 
    rowData = dates[date]; 
    recorders.forEach(function(recorder) { 
    var value = rowData.hasOwnProperty(recorder) ? rowData[recorder] : ''; 
    row.push(value) 
    }); 
    res.push(csvRow(row)) 
}); 

// final csv result string 
var csv = res.join('') 


// row csv helper 
function csvRow(arr){ 
    return '"'+ arr.join('","')+'"\n' 
} 
// helper 
function getDateString(date) { 
    return date.toISOString().slice(0, 10); 
} 

DEMO

+0

большое спасибо за ваше время! – XeniaSis

+0

по какой-то причине сортировка по дате работает некорректно везде. должен был возвратить 'new Date (a) -Новую дату (b)' – XeniaSis

+0

да ... Я бросил это как быстро, просто для концепции. Строка сравнить не лучшие – charlietfl