Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 25.07.2021, 20:24
Motorolla Motorolla вне форума
Прохожий
 
Регистрация: 06.06.2019
Сообщения: 17
Версия Delphi: Delphi 7 / XE8
Репутация: 10
По умолчанию Пересобрать двухмерный массив в массив записей

Есть большой файл (131Мб) содержащий данные 2x4 байт. Для удобства его можно представить как record длиной более 32млн записей.
Код:
TRec = record
A,B: integer;
end;
:
Замечено, что значение А последовательно (что-то вроде индекса с неопределённым инкрементом), а вот значение В может дублироваться многократно. Файл этот получаю со стороны и на его формирование влиять не могу, но хочу оптимизировать и объём и время поиска. Сейчас прямой поиск всех значений А при запрошенном В занимает 1,5 минуты.
Я планирую создать новый тип записи вида
Код:
TNewRec = packed record
B:integer;
Count:byte;
A: array of integer;
end;
Так я смогу собрать все значения A для запрашиваемого В, что даст мне уменьшение файла в несколько раз и если сразу отсортирую значения В, то сократится и время поиска.
Другого метода в голову пока не приходит. Но к сожалению и с этим-то я пока не могу разобраться. Получается, если на 1 проход для поиска всех совпадений затрачено 1,5 минуты, то по сути положение основного курсора (место очередного значения В) в потоке будет смещаться слишком медленно. На калькуляторе это выдало более 25млн минут и экспонента времени ближе к концу тут не особо поможет.
Как же мне преобразовать этот файл? Вернее задача даже заключается в том как уменьшить исходный файл и сократить в нём время поиска?

Последний раз редактировалось Motorolla, 25.07.2021 в 20:29.
Ответить с цитированием
  #2  
Старый 26.07.2021, 18:06
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 7,993
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

В общем, идея праильная.

Вариант.
Читаем файл и перекодируем его в вид:
<Bi - {Am,An,...}>
Т.е. Map с ключем B и заначением в виде списка A.

Т.о, получаем практически мгновенный поиск по B (за счет внутреннего механизма Map).

Ну и сохранять можно точно так же.

Но в этом случае поиск по A будет практически невозможным.
Ответить с цитированием
Этот пользователь сказал Спасибо lmikle за это полезное сообщение:
Motorolla (26.07.2021)
  #3  
Старый 26.07.2021, 22:42
Motorolla Motorolla вне форума
Прохожий
 
Регистрация: 06.06.2019
Сообщения: 17
Версия Delphi: Delphi 7 / XE8
Репутация: 10
По умолчанию

Спасибо! Осталось разобраться как создаются и обрабатываются эти мар файлы. Пока тёмный лес...
Ответить с цитированием
  #4  
Старый 27.07.2021, 21:46
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 7,993
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Map - это не файл. Это программный контейнер. Как ты его сохранишь в файл (и как будешь читать потом) - это уже твое дело. Можно, например, сохранять в бинарный файл.
Пусть не будем использовать стандарный контейнер, а используем "самописный":
Код:
type
  TMapItem = record
    B : Integer;
    As : Array Of Integer
  end;

var
  dataFile : Array Of TMapItem;

procedure SaveMap(AFileName : String)
var
  Stream : TFileStream;
  C, I, J : Integer;
begin
  Stream := TFileStream.Create(AFileName,foCreate);
  Try
    C := Length(dataFile);
    Stream.WriteBuffer(C,sizeOf(Integer);
    For I := Low(dataFile) To High(dataFile) Do
      Begin
        Stream.WriteBuffer(dataFile[i].B,SizeOf(Integer));
        C := Length(dataFile[i].As);
        Stream.WriteBuffer(C,SizeOf(Integer));
        For J := Low(dataFile[i].As) To High(dataFile[i].As) Do
          Stream.WriteBuffer(dataFile[i].As[J],SizeOf(Integer));
      End;
  Finally
    Stream.Free;
  End;
end;
Чтение в обратном порядке.
Принцип записи массивв - сначала пишем кол-во элементов, потом сами элементы.
Ответить с цитированием
Этот пользователь сказал Спасибо lmikle за это полезное сообщение:
Motorolla (27.07.2021)
  #5  
Старый 27.07.2021, 23:04
Motorolla Motorolla вне форума
Прохожий
 
Регистрация: 06.06.2019
Сообщения: 17
Версия Delphi: Delphi 7 / XE8
Репутация: 10
По умолчанию

Да, мал помалу стало понятно как работать с map и что это вообще такое, хотя не просто найти внятное описание с примерами. С сохранением как раз вопрос в воздухе и витал. Теперь тот же поиск всех столкновений составил 350mS!!!
Спасибо ещё раз за помощь!

Последний раз редактировалось Motorolla, 27.07.2021 в 23:12.
Ответить с цитированием
  #6  
Старый 28.07.2021, 01:37
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 7,993
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

А в Map не поиск. Там доступ по вычисляемому ключу
Ну типа как вычислить хэш от ключевого поля и использовать его как индекс в массиве. Это грубо, но поясняет принцип.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 06:03.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter