Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 23.09.2017, 10:12   #1
navprog
 
Регистрация: 23.09.2017
Сообщений: 5
Сообщение Применеие поправок для файла по времени

Всем здравия.
Задача следующая: есть исходный файл вида
8889.029 33703.950 194431 270810. 445.
8889.040 33703.912 194444 270810. 443.
8889.049 33703.872 194457 270810. 445.
... где 3-й столбец время, 4-й - дата, а 5-ый величина, которую надо поправить

есть второй файл вида
23,00,26,08,2010,3.00
00,00,27,08,2010,4.07
01,00,27,08,2010,1.11
... где 1-е поле - час, 2-е - минуты, 3-е число, 4-е мес 5-е год, 6-е - поправка, которую надо применить к пятому столбцу первого файла.

Оба файла имеют данные за недели-месяцы. Не могу понять алгоритм как мне добиться применения поправок к исходному файлу.
Подскажите, пожалуйста, как легче всего решить задачу. Delphi. Спасибо!

Последний раз редактировалось navprog; 23.09.2017 в 11:08.
navprog вне форума Ответить с цитированием
Старый 23.09.2017, 14:49   #2
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,238
По умолчанию

а как связаны первый файл и второй?

вот, например, Вы же привели содержимое файлов ДО изменения.
покажите, какие строчки, как именно (и почему они и именно так) должны измениться.
приведите их после коррекции.

p.s. я думаю, что я смог бы помочь Вам с кодом на Delphi, но, честно говоря, задачка не элементарная (достаточно много будет рутины по парсингу/конвертации).
Это, конечно, только в том случае, если понятно, как связаны файлы!
Serge_Bliznykov вне форума Ответить с цитированием
Старый 24.09.2017, 04:12   #3
navprog
 
Регистрация: 23.09.2017
Сообщений: 5
По умолчанию

Первый файл содержит "сырые данные", которые надо поправить значениями из второго файла, связь между ними по дате/времени. Я закинул архив, там 3 файла за сутки, 1-й с "сырыми" данными, второй - с поправками и третий - с результатом.
Мне приходит на ум, что при считывании строки с первого файла, надо открывать весь второй файл и искать совпадение по дате и времени, проверять, что значения второго файла находятся в диапазоне значений первого, применять поправку, и так на каждую запись первого. Но это громоздко что ли, не знаю как назвать, и я думаю есть более простой и эффективный метод.
Вложения
Тип файла: rar files.rar (1.01 Мб, 9 просмотров)
navprog вне форума Ответить с цитированием
Старый 24.09.2017, 04:34   #4
navprog
 
Регистрация: 23.09.2017
Сообщений: 5
По умолчанию

Смысл второго файла: допустим первая, вторая и третья строки
23,00,04,09,2017,4.00
23,15,04,09,2017,1.02
23,30,04,09,2017,9.03

это значит, что для первого файла все записи 5-го столбца в диапазоне по времени от 23:00:00 до 23:14:59 от 4-го сентября 17-го года должны быть исправлены на значение, равное "4,00" (т.е. к значению из первого файла должно быть прибавлено "4.00") , к записям в диапазоне от 23:15:00 до 23:29:59 надо прибавить "1,02" и так далее.
Дискретность второго файла может быть любой (например, каждые 10, 15, 20 минут или каждый час), но интервал всегда постоянен. Т.е. если разница между первой и второй записью второго файла 15 минут, то и все следующие записи также идут с интервалом 15 минут

Последний раз редактировалось navprog; 24.09.2017 в 07:44.
navprog вне форума Ответить с цитированием
Старый 25.09.2017, 08:39   #5
Slym
Участник клуба
 
Регистрация: 07.12.2011
Сообщений: 1,025
По умолчанию

пока без интервалов, и проверки боундов:
Код:
procedure TForm1.Button2Click(Sender: TObject);
const line=' 8889.029 33703.950 230031 260810. 445.';
const line2='23,00,26,08,2010,3.00';
var
  Data,Data2:TArray<string>;
  dt2,tm2:string;
  x:double;
  result:string;
begin
  Data:=line.Split([' '],ExcludeEmpty);
  Data2:=line2.Split([','],ExcludeEmpty);
  dt2:=Data2[2]+Data2[3]+Data2[4].Substring(2,2);
  tm2:=Data2[0]+Data2[1];
  if Data[3].StartsWith(dt2) then
  begin
    if Data[2].StartsWith(tm2) then
    begin
      x:=double.Parse(Data[4].Replace('.',',').Replace(',',FormatSettings.DecimalSeparator));
      x:=x+double.Parse(Data2[5].Replace('.',',').Replace(',',FormatSettings.DecimalSeparator));
      result:=x.ToString.Replace(FormatSettings.DecimalSeparator,'.');
      if result.IndexOf('.')<0 then result:=result+'.';

      caption:=line.Substring(0,line.Length-Data2[4].length)+result;
      //line=' 8889.029 33703.950 230031 260810. 447.';
    end;
  end;
end;
2ndfile.txt - сортирован? или диапазоны надо сортировать?
конец диапазона для последней строки 2ndfile.txt?
Не стесняемся, плюсуем!

Последний раз редактировалось Slym; 25.09.2017 в 08:42.
Slym вне форума Ответить с цитированием
Старый 25.09.2017, 09:29   #6
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,238
По умолчанию

Slym, жаль не могу запустить ваш код - Вы используете Delphi Xx


Цитата:
Сообщение от Slym Посмотреть сообщение
2ndfile.txt - сортирован?
думаю, что он у TC всегда в отсортированном виде, можно это принять как обязательное условие работы.


Цитата:
Сообщение от Slym Посмотреть сообщение
конец диапазона для последней строки 2ndfile.txt?
во, хороший вопрос.
но TC утверждает, что в этом файле интервал всегда строго один и тот же.
поэтому, можно считать, что последняя строчка действует время от того, что в ней указано + интервал (это разница по времени с предыдущей/предпоследней строчкой).
Serge_Bliznykov вне форума Ответить с цитированием
Старый 25.09.2017, 12:54   #7
Slym
Участник клуба
 
Регистрация: 07.12.2011
Сообщений: 1,025
По умолчанию

немного анализа входных файлов:
судя по выходным данным нужно не складывать, а отнимать...
1 строка 1stfile.txt
6870.056 51451.774 001452 050917. 00069.2
ей соответствует 5 строка 2ndfile.txt
00,00,05,09,2017,4.07
в resultfile.txt получаем:
6870.056 51451.774 001452 050917. 00065.2
а по идее должны получить
6870.056 51451.774 001452 050917. 00065.13

resultfile.txt - не правильный?

мой базовый Delphi7, но не хотел заморачиваться со Split поэтому Delphi10.2
и тупо полный перебор, хотя можно минимум вдвое убыстрить начиная поиск от предыдущей итерации
Код:
procedure TForm1.Button1Click(Sender: TObject);
var
  DiffData,Data:TStringList;
  StrSt,StrEnd,StrData:TArray<string>;
  i,j:integer;
  StartDt,EndDt,AvgDt,Dt:TDateTime;
  Diff,Value:double;
  Str:string;
begin
  FormatSettings.DecimalSeparator:='.';
  DiffData:=TStringList.Create;
  try
    DiffData.LoadFromFile('.\files\2ndfile.txt');
    Data:=TStringList.Create;
    try
      Data.LoadFromFile('.\files\1stfile.txt');
      for i:=0 to DiffData.Count-1 do
      begin
        StrSt:=DiffData[i].Split([','],ExcludeEmpty);
        if Length(StrSt)<>6 then Continue;
        StartDt:=EncodeDateTime(StrSt[4].ToInteger, StrSt[3].ToInteger,
            StrSt[2].ToInteger, StrSt[0].ToInteger, StrSt[1].ToInteger,0,0);
        Diff:=double.Parse(StrSt[5]);

        if i<DiffData.Count-1 then
        begin
          StrEnd:=DiffData[i+1].Split([','],ExcludeEmpty);
          if Length(StrEnd)<>6 then Continue;
          EndDt:=EncodeDateTime( StrEnd[4].ToInteger, StrEnd[3].ToInteger,
            StrEnd[2].ToInteger, StrEnd[0].ToInteger, StrEnd[1].ToInteger,0,0);
        end else
        begin
          EndDt:=StartDt+AvgDt;
        end;
        AvgDt:=EndDt-StartDt;

        Caption:=(i+1).ToString+'/'+DiffData.Count.ToString;
        Application.ProcessMessages;
        for j:=0 to Data.Count-1 do
        begin
          StrData:=Data[j].Split([' '],ExcludeEmpty);
          if Length(StrData)<>5 then Continue;

          Dt:=EncodeDateTime(
            ('20'+StrData[3].Substring(4,2)).ToInteger,
            StrData[3].Substring(2,2).ToInteger,
            StrData[3].Substring(0,2).ToInteger,
            StrData[2].Substring(0,2).ToInteger,
            StrData[2].Substring(2,2).ToInteger,
            StrData[2].Substring(4,2).ToInteger,0);

          if DateInRange(Dt,StartDt,EndDt) then
          begin
            Value:=double.Parse(StrData[4]);
            Value:=Value-Diff;
            Str:=Data[i];

            Str:=Str.Substring(0,Str.Length-StrData[4].length)+FormatFloat('00000.0',Value);
            Data[i]:=Str;
          end;
        end;
      end;

      Data.SaveToFile('.\files\Slym_resultfile.txt');
    finally
      Data.Free;
    end;
  finally
    DiffData.Free;
  end;
end;
Не стесняемся, плюсуем!

Последний раз редактировалось Slym; 25.09.2017 в 13:17. Причина: ЮБИЛЕЙНЫЙ ПОСТ :)
Slym вне форума Ответить с цитированием
Старый 25.09.2017, 13:24   #8
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,238
По умолчанию

Цитата:
Сообщение от Slym Посмотреть сообщение
а по идее должны получить
6870.056 51451.774 001452 050917. 00065.13
абсолютно согласен.
похоже, что поправка берётся с отбрасыванием сотых.
но, разумеется, этот момент нужно обязательно уточнить в ТС
Serge_Bliznykov вне форума Ответить с цитированием
Старый 26.09.2017, 00:49   #9
navprog
 
Регистрация: 23.09.2017
Сообщений: 5
По умолчанию

Цитата:
немного анализа входных файлов:
судя по выходным данным нужно не складывать, а отнимать...
Это на самом деле опционально, не имеет значения в данном случае, это будет зависеть от выбора пользователя. Эти файлы используются для построения батиметрии (данных по морским/речным глубинам), а второй файл несет в себе предрассчитанные поправки за приливно-отливные изменения уровня воды. И там в зависимости от референсной точки поправки могут быть либо прибавлены либо вычтены.
Я попробывал сделать топорно: считал в динамические массивы значения второго файла при загрузке и на каждую строку первого файла проверку на совпадение. Работает, но время жрёт уйму.
Код:
var
af:textfile;

pk:integer;
begin
try
if od.Execute then
  begin
  assignfile(af,od2.FileName);
  reset(af);
    pk:=0;
  while not eof(af) do
    begin
    readln(af);
    pk:=pk+1;
    end;
  closefile(af);
  setlength(ptimes,pk);
  setlength(pmonth,pk);
  setlength(pday,pk);
  setlength(pvalue,pk);
  setlength(pyear,pk);
  setlength(ptimef,pk-1);
  reset(af);
  while not eof(af) DO
    begin

    for pj:=0 to pk-1 do
      begin
      read(af,bigs);
      ptimes[pj]:=copy(bigs,1,5);
      ptimes[pj]:=stringreplace(ptimes[pj],',','',[rfReplaceAll]); //tfs - tformatsettings, //tfs.decimal:='.';
      pday[pj]:=copy(bigs,7,2);
      pmonth[pj]:=copy(bigs,10,2);
      pyear[pj]:=copy(bigs,13,4);
      pvalue[pj]:=strtofloat(copy(bigs,18,length(bigs)-16),tfs);
      pvalues[pj]:=formatfloat('0.00',pvalue[pj],tfs);
      readln(af);
      end;

    end;
    for pj:=0 to pk-2 do   //сюда гружу данные конца интервала
    ptimef[pj]:=ptimes[pj+1];
    showmessage('Файл загружен');

    button1.Enabled:=true;

  end;

except showmessage('Файл приливов не загружен');
 end;

end;
и потом проверка по времени/дате

Код:
chk:=false;
for pj:=0 to pk-1 do
        begin
        if (copy(ndate,1,2)=pday[pj]) and (mondate=pmonth[pj]) and (copy(time1,1,2)=copy(ptimes[pj],1,2)) and (strtoint(copy(time1,3,2)) < strtoint(copy(ptimef[pj],3,2))) and (chk=false) then
           begin

           depthr:=depthr+(pvalue[pj]*10);
           chk:=true;
           end;

        end;
Это топорно, я понимаю, занимает процессорное время.
Сейчас буду пробовать код Slym, у меня 7-я версия Deplhi.
Спасибо вам за отзывчивость и советы
navprog вне форума Ответить с цитированием
Старый 26.09.2017, 00:49   #10
navprog
 
Регистрация: 23.09.2017
Сообщений: 5
По умолчанию

Файлы содержат много записей, первый пишется на сутки ежесекундно, около 86000 записей, второй с поправками содержит около 3-х месяцев предрасчётов (около 5000 записей) и поэтому выполнение моего "алгоритма" занимает много время

Последний раз редактировалось navprog; 26.09.2017 в 01:01.
navprog вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

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

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


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Создание анимированного по времени KML файла на Java Айсулу Курмашева Помощь студентам 0 01.02.2015 17:19
Чтение даты и времени из файла triest Помощь студентам 5 18.05.2011 23:33
Посоветуйте наиболее актуальные для нашего времени книги и программы для программирования и отладки. Lemax25 Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 10 09.03.2010 17:12
Фиксирование времени открытия файла eda Microsoft Office Excel 5 05.02.2009 11:52
Третий проект поправок, призванных учредить органы студенческого самоуправления в вузах и сузах страны. Alar Свободное общение 3 29.03.2008 21:09