Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2011.04.24;
Скачать: CL | DM;

Вниз

выделить из списка цепочки   Найти похожие ветки 

 
LDV   (2011-01-21 13:36) [0]

Есть отсортированный список пакетов обновления:

upd_1_to_2.zip
upd_2_to_3.zip
upd_3_to_4.zip
upd_7_to_11.zip
upd_11_to_12.zip
................

Задача: разбить список на цепочки (подсписки). т.е.

1-я цепочка
upd_1_to_2.zip
upd_2_to_3.zip
upd_3_to_4.zip

2-я цепочка
upd_7_to_11.zip
upd_11_to_12.zip

Делаю так:

1. Формирую TList<TPoint> (чтобы было удобней сравнивать), где

X - 1-е значение в имени пакета обновления
Y - 2-е значение в имени пакета обновления

2. Передаю TList<TPoint> в написанную процедуру split

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


procedure Split(const Afile_vers: TList<TPoint>;
 ASplitted: TObjectList<TList<TPoint>>);
var
 Cur: TPoint;
 I, N, J: Integer;
 Ok, Added: TList<TPoint>;
begin
 Ok := TList<TPoint>.Create(TComparer<TPoint>.Construct(

     function (const AVal1, AVal2: TPoint): Integer
     begin
       Result := CompareValue(AVal1.X, AVal2.Y)

     end
 ));
 for I := 0 to Afile_vers.Count - 1 do
 begin
   Cur := Afile_vers[I];
   try
     Ok.BinarySearch(Cur, N);
     { 1-е значение в имени текущего пакета обновления должно совпадать со
       2-значением в имени предшаствующего пакета, если текущй пакет не
       будет 1-м в списке (N <> 0)}
     if N <> 0 then

       Assert(Ok[N - 1].Y = Cur.X);

     {2-е значение в имени текущего пакета обновления должно совпадать с
       1-м значением в имени следующего пакета, если текущий пакет не будет
       последним в списке (N <> Ok.Count)}

     if N <> Ok.Count then

       Assert(Cur.Y = Ok[N].X);

     Ok.Insert(N, Cur);
   except
     Added := TList<TPoint>.Create;
     try
       for J := 0 to Ok.Count - 1 do
         Added.Add(Ok[J]);
       ASplitted.Add(Added);
       Ok.Clear;
       Ok.Add(Cur);
     except
       Added.Free;
       raise;
     end;
   end;

 end;
 Added := TList<TPoint>.Create;
 try
   for J := 0 to Ok.Count - 1 do
     Added.Add(Ok[J]);
   ASplitted.Add(Added);
 except
   Added.Free;
   raise;
 end;

end;

procedure TForm3.FormCreate(Sender: TObject);
var
 file_vers: TList<TPoint>;
 Splitted: TObjectList<TList<TPoint>>;
begin
 file_vers := TList<TPoint>.Create;
 try
   Splitted := TObjectList<TList<TPoint>>.Create;
   try
     { ... test }
     file_vers.Add(Point(1, 2)); // upd_1_to_2.zip
     file_vers.Add(Point(2, 3)); // upd_2_to_3.zip
     file_vers.Add(Point(3, 4)); // upd_3_to_4.zip
     file_vers.Add(Point(7, 11)); // upd_7_to_11.zip
     file_vers.Add(Point(11, 12)); // upd_11_to_12.zip

     Split(file_vers, Splitted);

     ShowMessage("Цепочек: " + IntToStr(Splitted.Count));
     { ... }
   finally
     Splitted.Free;
   end;
 finally
   file_vers.Free;
 end;

end;


 
Ega23 ©   (2011-01-21 13:49) [1]


> 1. Формирую TList<TPoint> (чтобы было удобней сравнивать)

Это нехорошо. Можно, но нехорошо. Напиши свой тип, используй его.


 
MBo ©   (2011-01-21 13:49) [2]


цикл
 Взяли i-ю строку.
 Выделили из нее X и Y.
 Если X не совпадает с OldY, то
     Получили цепочку от Start до i-1, выдаем ее в результат
     Start = i
 OldY = Y
конец цикла, выдаем последнюю цепочку


 
han_malign   (2011-01-21 16:21) [3]


>  Взяли i-ю строку.
>  Выделили из нее X и Y.

- для не последовательного ввода и/или кэширования "звеньев":
const
  RANGE_BEGIN = $80000000;
  RANGE_END   = $40000000;
  RANGE_VALUE = $3FFFFFFF;

  function compare(x1, x2: LongWord): integer;
  begin
       Result:= LongInt(x1 and RANGE_VALUE) - LongInt(x2 and RANGE_VALUE);
  end;

procedure AddRange(X, Y: longword);
var i: integer;
begin  
  i:= FindOrInsert(rgdwRanges, X, compare);
  rgdwRanges[i]:= rgdwRanges[i] or RANGE_BEGIN;
  i:= FindOrInsert(rgdwRanges, Y, compare);
  rgdwRanges[i]:= rgdwRanges[i] or RANGE_END;
end;

function ProcessRanges: integer;//return count of Continuous chains
var rangeStart: integer;
begin
  Result:= 0; rangeStart:= -1;
  for i:= Low(rgdwRanges) to High(rgdwRanges) do begin
     case(rgdwRanges[i] and (RANGE_BEGIN or RANGE_END))of
     0: Assert(false);
     RANGE_BEGIN: rangeStart:= rgdwRanges[i] and RANGE_VALUE;
     RANGE_END: begin
         Assert((i > Low(rgdwRanges)) and (integer(rangeStart) >= 0));
         ProcessFile(format("upd_%u_to_%u.zip", [rgdwRanges[i-1] and RANGE_VALUE, rgdwRanges[i] and RANGE_VALUE]));
         FlushContinuousRange(rangeStart, rgdwRanges[i] and RANGE_VALUE);
         inc(Result);
     end;
     else //(RANGE_BEGIN or RANGE_END) - intermediate joint
         Assert(i > Low(rgdwRanges));
         ProcessFile(format("upd_%u_to_%u.zip", [rgdwRanges[i-1] and RANGE_VALUE, rgdwRanges[i] and RANGE_VALUE]));
     end{case};
  end;
end;



Страницы: 1 вся ветка

Текущий архив: 2011.04.24;
Скачать: CL | DM;

Наверх




Память: 0.48 MB
Время: 0.01 c
15-1294926003
12
2011-01-13 16:40
2011.04.24
EhLib v3.6. Нормально работает?


2-1240595519
Артем
2009-04-24 21:51
2011.04.24
открыт ли порт?


2-1295179948
azl
2011-01-16 15:12
2011.04.24
Добавление разноцветной форматированной строки в RichEdit


2-1295368393
Ярослав
2011-01-18 19:33
2011.04.24
TStringList + много данных


11-1233219482
chum
2009-01-29 11:58
2011.04.24
Как перевести проект с 7 на 10.