Проверка и сохранение строк

Рейтинг: 0Ответов: 1Опубликовано: 04.03.2023

Я проверяю дубликаты строк до символа =. И если строки есть то сохранить не удаляя дубликаты.

var f, s: TStringDynArray;
    i, j, k: integer;
    L, L1: TStringList;
    index: array of integer;
begin
 L := TStringList.Create;
 L1 := TStringList.Create;
 j := 0;
 // грузим файл
 f := TFile.ReadAllLines('1.txt');
 // Проходим в цикле
 for i := Low(f) to High(f) do
  begin
   // делим строку
   s := SplitString(f[i], '=');
   // первая часть стоки до знака =
   k := L.IndexOf(s[0]);
   if k = -1
    then
     begin
      inc(j);
      L.AddObject(s[0], TObject(1));
      SetLength(Index, j);
      Index[j - 1] := i;
     end
    else L.Objects[k] := TObject(Integer(L.Objects[k]) + 1);
  end;
 for i := 0 to High(Index) do
 if Integer(L.Objects[i]) <> 1 then L1.Add(f[Index[i]]);
 L1.SaveToFile('Выход.txt');
 L1.Free;
 L.Free;
end;

Пример строк

123=5678
324=345678
333=7678333
333=5457788
222=347678
222=47878888

На выходе должно получится

333=7678333
333=5457788
222=347678
222=47878888

А у меня получается.То есть еще и дубликаты удаляются а должны сохранится.

333=7678333
222=347678

Ответы

▲ 3Принят

Как-то слишком перегружено ИМХО.

Кроме того, список ключей и значений, разделённый символом '=' - это штатная конструкция, про которую знает TStringList и умеет с ней работать.

Вот пример кода, который решает указанную задачу. Неоптимальным способом, зато максимально просто.

var
  Source: TStrings;
  Value: string;
  Index: Integer;
  Found: Integer;
begin
  Source := TStringList.Create;
  Source.LoadFromFile('C:\Projects\Tests\1.txt');
  { Начинаем с конца, потому что IndexOfName() возвращает
    только первое найденное значение }
  Index := Source.Count - 1;
  { До тех пор пока не пройдём весь список до начала }
  while Index >= 0 do
  begin
    { Получаем значение ключа }
    Value := Source.KeyNames[Index];
    { Ищем парное ему значение }
    Found := Source.IndexOfName(Value);
    { Если нашли именно дубликат, а не себя }
    if (Found >= 0) and (Found < Index) then
      { То отмечаем его чтобы не проверять заново }
      Source.Objects[Found] := TObject(True)
    else
      { Иначе удаляем элемент без дубликатов }
      Source.Delete(Index);
    { Смещаемся вверх на один элемент }
    Dec(Index);
    { Пропускам уже найденные дубликаты }
    while (Index >= 0) and (Source.Objects[Index] = TObject(True)) do
      Dec(Index);
  end;
  Source.SaveToFile('C:\Projects\Tests\2.txt');
  Source.Free;
end.

UPD: Исправил код чтобы он не выдавал исключение, если в списке строки без разделителей.