Solved

Comma-seperated sub string extract

Posted on 1999-01-08
12
660 Views
Last Modified: 2010-04-06
I have a string containing comma-seperated values:

1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20

i.e. 20 values with commas seprating them (18 commas)

This string we will call MainString

I want a function will the following call

ExtractSubString(MainString, Start, Finish): string
where
 MainString is the string above
 Start is the first value to extract
 Finish is the last value to extract

ExtractSubString returns a string containing the substring

For example, I call ExtractSubString with the following parameters:

MainString,1,20
the returned substring looks like this:
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20

or
MainString,5,20
the returned substring looks like this:
5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20

or

MainString,5,15
the returned substring looks like this:
5,6,7,8,9,10,11,12,13,14,15

or

MainString,19,20
the returned substring looks like this:
19,20

i.e. I want to keep the commas intact

A function that does these three examples perfectly wins the points. It must also be fast. i don't need to know the actul values at any point so you can keep the whole thing as strings.

Cheers

Ian

0
Comment
Question by:iwatkins
  • 5
  • 3
  • 2
  • +2
12 Comments
 

Author Comment

by:iwatkins
ID: 1355252
Adjusted points to 400
0
 
LVL 3

Accepted Solution

by:
Ronald Buster earned 400 total points
ID: 1355253
Hi,

Here the solution for your problem, tested it on your 3 examples and it worked.

Enjoy

Regards,

Cono


<---CUT HERE----->

function ExtractSubString(Value : String; pos1,pos2 : integer ) : string;
var s1,s2 : string;
begin
  Result := '';

  s1 := Trim(Value);
  while pos(',',s1) > 0 do
    begin
      s2 := copy(s1,1,pos(',',s1)-1);
      if (StrToInt(s2) >= pos1) and (StrToInt(s2) <= pos2) then
        begin
          Result := Result + s2 + ',';
        end;
      delete(s1,1,pos(',',s1));
    end;

  if (StrToInt(s1) >= pos1) and (StrToInt(s1) <= pos2) then
    begin
      Result := Result + s1;
    end;
end;

<---CUT HERE----->
0
 
LVL 5

Expert Comment

by:heathprovost
ID: 1355254
Here is my version

function ExtractSubString(MainString: String; Start, Finish: integer): string;
var
  TempString: String;
  CommaCount: integer;
  StartPos, EndPos: integer;
  StringLength: integer;
begin
  TempString := ',' + MainString + ',';
  StringLength := Length(TempString);
  CommaCount := 0;
  StartPos := 1;
  Repeat
    if TempString[StartPos] = ',' then Inc(CommaCount);
    Inc(StartPos);
    if StartPos = StringLength then
    begin
      Result := 'ERROR';
      Exit;
    end;
  Until CommaCount = Start;
  CommaCount := 0;
  EndPos := StartPos + 1;
  Repeat
    if TempString[EndPos] = ',' then Inc(CommaCount);
    Inc(EndPos);
    if EndPos = StringLength then
    begin
      Result := 'ERROR';
      Exit;
    end;
  Until CommaCount = Finish - Start + 1;
  Result := Copy(TempString, StartPos, EndPos - StartPos - 1);
end;

Heath
0
 
LVL 5

Expert Comment

by:heathprovost
ID: 1355255
Condensed a bit


function ExtractSubString(MainString: String; Start, Finish: integer): string;
var
  TempString: String;
  CommaCount: integer;
  StartPos, EndPos: integer;
  StringLength: integer;
begin
  Result := 'ERROR';
  TempString := ',' + MainString + ',';
  StringLength := Length(TempString);
  CommaCount := 0;
  StartPos := 1;
  Repeat
    if TempString[StartPos] = ',' then Inc(CommaCount);
    Inc(StartPos);
    if StartPos = StringLength then
      Exit;
  Until CommaCount = Start;
  CommaCount := 0;
  EndPos := StartPos + 1;
  Repeat
    if TempString[EndPos] = ',' then Inc(CommaCount);
    Inc(EndPos);
    if EndPos = StringLength then
      Exit;
    end;
  Until CommaCount = Finish - Start + 1;
  Result := Copy(TempString, StartPos, EndPos - StartPos - 1);
end;


Heath
0
 
LVL 5

Expert Comment

by:heathprovost
ID: 1355256
The best I can do.....(Fixed bug in error code and condensed a bit more)

function ExtractSubString(MainString: String; Start, Finish: integer): string;
var
  TempString: String;
  CommaCount: integer;
  StartPos, EndPos: integer;
  StringLength: integer;
begin
  Result := 'ERROR';
  TempString := ',' + MainString + ',';
  StringLength := Length(TempString);
  CommaCount := 0;
  StartPos := 1;
  Repeat
    if StartPos > StringLength then Exit;
    if TempString[StartPos] = ',' then Inc(CommaCount);
    Inc(StartPos);
  Until CommaCount = Start;
  CommaCount := 0;
  EndPos := StartPos + 1;
  Repeat
    if EndPos > StringLength then Exit;
    if TempString[EndPos] = ',' then Inc(CommaCount);
    Inc(EndPos);
  Until CommaCount = Finish - Start + 1;
  Result := Copy(TempString, StartPos, EndPos - StartPos - 1);
end;

Heath
0
 

Author Comment

by:iwatkins
ID: 1355257
Easy when you know how !

Things are clear, and it works.

Cheers

Cono
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 27

Expert Comment

by:kretzschmar
ID: 1355258
hi,

a other way, with strings


function selectpart(source, Starting, Ending : String) : String;
begin
  If pos(Starting,source) = 0 then
    result := 'Start not found'
  else
    If pos(Ending,source) = 0 then
      result := 'End not found'
    else
      If pos(Ending,source) < pos(Starting,source) then
        result := 'End before Start'
      else
        result := copy(source,pos(starting,source),pos(Ending,source)+Length(Ending)-pos(starting,source));
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  edit4.text := SelectPart(edit1.text,edit2.text,edit3.text);
end;


meikl
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 1355259
Hi,

it seems i am a little late for this q

meikl
0
 
LVL 5

Expert Comment

by:heathprovost
ID: 1355260
No offense intended, But his cono's functin does NOT do what you asked.  for example:

ExtractSubString('1,2,3,4,5,6,7,8,9,0', 1, 9) returns

"1,2,3,4,5,6,7,8,9," not "1,2,3,4,5,6,7,8,9"

also

ExtractSubString('100,200,300,400,500,600,700,800,900,1000', 1, 9) returns

NOTHING!

I wrote my function to be generic, as in ALL input in the format you specified returns valid results.  I think you should be more careful evaluating things next time.

Heath
0
 
LVL 3

Expert Comment

by:Matvey
ID: 1355261
Ooooh, man, I'm a bit late... Do you want to see what a beauty I made? Well, I have nobody else to show this to, so here it is:
________________________________________________________________
function ExtractSubString(MainString: string; Start, Finish: integer): string;
var
  AP: TParser;
  SS: TStringStream;
  CI, StartPos, EndPos: integer;
begin
  SS := TStringStream.Create(MainString);
  AP := TParser.Create(SS);
  CI := 1;
  with AP do begin
    repeat
      if Token = ',' then begin inc(CI); NextToken; end;
      if CI <= Start then StartPos := SourcePos;
    until (NextToken = #0) or (CI >= Finish);
    EndPos := SourcePos;
  end;
  Result := Copy(MainString, StartPos+1, EndPos-StartPos);
  AP.Free;
  SS.Free;
end;
________________________________________________________________
0
 
LVL 5

Expert Comment

by:heathprovost
ID: 1355262
Hey Matvey, that one real nice :)
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 1355263
Matvey,

really late, but a tricky way

meikl
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …
I designed this idea while studying technology in the classroom.  This is a semester long project.  Students are asked to take photographs on a specific topic which they find meaningful, it can be a place or situation such as travel or homelessness.…

914 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now