Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 28.07.2018, 10:18
Новичок на форуме
Отправить личное сообщение для niko45 Посмотреть профиль Найти все сообщения от niko45
 
Регистрация: 20.11.2014
Сообщений: 7

Помогите решить задачку с массивами
Всем привет!

Необходимо найти наибыстрейшее решение на 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 лет. Спасибо за помощь!
Ответить с цитированием
  #2 (permalink)  
Старый 28.07.2018, 11:59
Аватар для Alexandroppolus
Профессор
Отправить личное сообщение для Alexandroppolus Посмотреть профиль Найти все сообщения от Alexandroppolus
 
Регистрация: 25.10.2016
Сообщений: 1,012

Если оба массива отсортированы по дате, то можно за линейное время сделать, параллельно идя по обоим массивам, это самый быстрый вариант.

Иначе - либо отсортировать оба, либо использовать поиск делением пополам, либо по одному из массивов создать карту дата->элемент для массива с торгами.

В общем, главное не делать вложенный цикл )

Последний раз редактировалось Alexandroppolus, 28.07.2018 в 12:02.
Ответить с цитированием
  #3 (permalink)  
Старый 28.07.2018, 13:31
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,105

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>
Ответить с цитированием
  #4 (permalink)  
Старый 28.07.2018, 13:45
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,105

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>
Ответить с цитированием
  #5 (permalink)  
Старый 28.07.2018, 14:07
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,990

niko45,
второй массив содержит все даты, то есть 365, а значит и нерабочие дни тоже? Если так, то зачем он нужен, можно же узнать рабочая или нет первая дата первого массива и по крайней мере учесть дни не субботние и воскресные и без второго массива.
Ответить с цитированием
  #6 (permalink)  
Старый 28.07.2018, 14:33
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,577

Если массивы 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));

Тем более что вариант рони всё рано меняет исходные массивы.)
__________________
29375, 35
Ответить с цитированием
  #7 (permalink)  
Старый 28.07.2018, 15:08
Аватар для Alexandroppolus
Профессор
Отправить личное сообщение для Alexandroppolus Посмотреть профиль Найти все сообщения от Alexandroppolus
 
Регистрация: 25.10.2016
Сообщений: 1,012

Массив b - возможно, массив строк, а не объектов. Тогда придётся новый массив создавать, по крайней мере для пустых дат (непустые можно взять из а)
Ответить с цитированием
  #8 (permalink)  
Старый 28.07.2018, 15:57
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,577

Alexandroppolus,
if (a[j].date === b[i]) b[i] = a[j++];
else b[i] = {date: b[i], empty: true};
__________________
29375, 35
Ответить с цитированием
  #9 (permalink)  
Старый 28.07.2018, 19:10
Новичок на форуме
Отправить личное сообщение для niko45 Посмотреть профиль Найти все сообщения от niko45
 
Регистрация: 20.11.2014
Сообщений: 7

спасибо всем откликнувшийся, проверю каждый вариант по времени исполнения.

Еще уточнение - массив a набирается из csv файла, где хранятся котировки, они отсортированы по возрастанию даты, но сами даты могут быть с дырами, выходными, праздниками или просто отсутствием данных, т.е. за понедельником может идти сразу пятница.

Цитата:
1998.01.05;00:00;5.995;5.995;5.995;5.995;1
1998.01.06;00:00;5.999;5.999;5.999;5.999;1
1998.01.08;00:00;6.000;6.000;6.000;6.000;1
1998.01.09;00:00;5.999;5.999;5.999;5.999;1
1998.01.12;00:00;6.003;6.003;6.003;6.003;1
Думаю еще упростить, сократив один цикл - если есть возможность читать csv построчно, а массив b сделать ассоциативным с ключами вида b["19980105" => value], то рассортировать можно тупо обратившись по ключу.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Помогите решить задачу с массивами! KaTaJLonec Общие вопросы Javascript 4 02.02.2015 00:25
Помогите решить задачку на jQuery. Готов заплатить. shevgeny Javascript под браузер 1 05.05.2014 12:07
Помогите решить задачи с массивами Konstan_G Работа 11 13.05.2013 22:10
Помогите решить задачку. Андрей_ Javascript под браузер 3 26.06.2012 16:21
Помогите решить задачку valero Элементы интерфейса 10 07.03.2010 16:41