Помогите решить задачку с массивами
Всем привет!
Необходимо найти наибыстрейшее решение на javascript, т. е. наиболее эффективное с точки зрения времени исполнения браузером. Есть массив a, который содержит результаты торгов на бирже за день: var a=[ {date: "19980105", open: 5.995, high: 6, low: 5.995, close: 5.999}, {date: "19980108", open: 5.993, high: 6, low: 5.993, close: 5.999} ] date - это номер рабочего дня в формате YYYYMMDD, как понимаете, торги идут только в рабочие дни. Далее есть массив b со всеми календарными днями. Он разумеется всегда больше массива a. Надо эффективно раскидать данные рабочих дней по массиву календарных дней, так чтобы в итоге получился массив с примерного вида: с=[ {date: "19980105", open: 5.995, high: 6, low: 5.995, close: 5.999}, {date: "19980106", empty: true}, {date: "19980107", empty: true}, {date: "19980108", open: 5.993, high: 6, low: 5.993, close: 5.999} ] Про массивы a и b точно известно, что они отсортированы по возрастанию времени date. Задачу сам я решил, но малоэффективно, здесь важно, что сами массивы очень здоровенные, т.к. интервалы времени вплоть до вековых, т.е. 365 дней * 100 лет. Спасибо за помощь! |
Если оба массива отсортированы по дате, то можно за линейное время сделать, параллельно идя по обоим массивам, это самый быстрый вариант.
Иначе - либо отсортировать оба, либо использовать поиск делением пополам, либо по одному из массивов создать карту дата->элемент для массива с торгами. В общем, главное не делать вложенный цикл ) |
niko45,
<script> const a=[ {date: "19980105", open: 5.995, high: 6, low: 5.995, close: 5.999}, {date: "19980108", open: 5.993, high: 6, low: 5.993, close: 5.999} ], b = [ {date: "19980105"}, {date: "19980106"}, {date: "19980107"}, {date: "19980108"} ]; function fn(a,b) { a = a.reduce((a,b) => ({date,...d} = b, a[date] = d, a), {}) return b.map(b => ({date} = b, {...b, ...(a[date] ||{empty: true})})) } const c = fn(a,b); document.write(JSON.stringify(c, null, 4)) </script> |
niko45,
<script> var a=[ {date: "19980105", open: 5.995, high: 6, low: 5.995, close: 5.999}, {date: "19980108", open: 5.993, high: 6, low: 5.993, close: 5.999} ], b = [ {date: "19980105"}, {date: "19980106"}, {date: "19980107"}, {date: "19980108"} ]; function fn(a, b) { var i = 0; return b.map(function(c) { if (a[i].date == c.date) return a[i++]; c.empty = true; return c }) }; var c = fn(a,b); document.write(JSON.stringify(c, null, 4)) </script> |
niko45,
второй массив содержит все даты, то есть 365, а значит и нерабочие дни тоже? Если так, то зачем он нужен, можно же узнать рабочая или нет первая дата первого массива и по крайней мере учесть дни не субботние и воскресные и без второго массива. |
Если массивы a и b потом не нужны, то эффективнее изменять b а не создавать новый:
var a=[ {date: "19980105", open: 5.995, high: 6, low: 5.995, close: 5.999}, {date: "19980108", open: 5.993, high: 6, low: 5.993, close: 5.999} ], b = [ {date: "19980105"}, {date: "19980106"}, {date: "19980107"}, {date: "19980108"} ]; function fn(a, b) { for(var i = 0, j = 0, l = b.length; i < l; i++){ if (a[j].date === b[i].date) b[i] = a[j++]; else b[i].empty = true; } return b }; var c = fn(a,b); alert(JSON.stringify(c, null, 4)); Тем более что вариант рони всё рано меняет исходные массивы.) |
Массив b - возможно, массив строк, а не объектов. Тогда придётся новый массив создавать, по крайней мере для пустых дат (непустые можно взять из а)
|
Alexandroppolus,
if (a[j].date === b[i]) b[i] = a[j++]; else b[i] = {date: b[i], empty: true};;) |
спасибо всем откликнувшийся, проверю каждый вариант по времени исполнения.
Еще уточнение - массив a набирается из csv файла, где хранятся котировки, они отсортированы по возрастанию даты, но сами даты могут быть с дырами, выходными, праздниками или просто отсутствием данных, т.е. за понедельником может идти сразу пятница. Цитата:
|
Часовой пояс GMT +3, время: 19:24. |