• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 307
  • Last Modified:

improving the split function

Hello guys,

I have a function that is at the bottom of the text, it split a sentence into a group of word.
I need a function, maybe the function can be used, a function that can create a stringlist with all
possible combination among words. example:
In her opinion the project was still imperfect.

the combinations that the function created
  <PHRASE>In her opinion the project was still imperfect.</PHRASE>
  <PHRASE>In</PHRASE>
  <PHRASE>her</PHRASE>
  <PHRASE>opinion</PHRASE>
  <PHRASE>the</PHRASE>
  <PHRASE>project</PHRASE>
  <PHRASE>was</PHRASE>
  <PHRASE>still</PHRASE>
  <PHRASE>imperfect.</PHRASE>
  <PHRASE>In her</PHRASE>
  <PHRASE>opinion the</PHRASE>
  <PHRASE>project was</PHRASE>
  <PHRASE>still imperfect.</PHRASE>
  <PHRASE>In her opinion</PHRASE>
  <PHRASE>the project was</PHRASE>
  <PHRASE>still imperfect.</PHRASE>
  <PHRASE>In her opinion the</PHRASE>
  <PHRASE>project was still imperfect.</PHRASE>

but as you can see, it is missing other possible combinations, such as:

was still
opnion the
the project

I hope you understand, thanks

procedure SplitSentence(Sentence: String; SplitNumber: Integer; const Words: TStrings);
var i, j: Integer;
    Delimit: Char;
    w: String;
begin
 Assert(Assigned(Words)); Delimit := ' ';
 with TStringList.Create do try
      Clear; Delimiter := Delimit;
      DelimitedText := Sentence;
      Words.Clear;
      if Count<=SplitNumber then begin
         Words.Add(Sentence); Exit;
      end;
      i:=-1;
      repeat
        Inc(i); w:=Strings[i];
        if i<(Count-1) then begin
           for j:=2 to SplitNumber do begin
               Inc(i); w:=w+Delimit+Strings[i];
               if i>=(Count-1) then Break;
           end;
        end;
        Words.Add(w);
      until i>=(Count-1);
 finally Free; end;
end;

// --------------- DEMO ------------------

procedure TForm1.Button1Click(Sender: TObject);
begin
  SplitSentence('I am here working with my sister and she is working right now', 2, Memo1.Lines);
end;
0
hidrau
Asked:
hidrau
3 Solutions
 
TheRealLokiSenior DeveloperCommented:
here's how I would do it ....

procedure SplitSentence(Sentence: String; StartCount, EndCount: Integer; const Words: TStrings);
const
  Delimiters = ' .,!?'#13#10;
var
  i, j, k: Integer;
  w: String;
  sl: TStringList;
begin
  sl := TStringList.Create;
  try
    for i := 1 to length(Delimiters) do
    begin
      Sentence := TRIM(StringReplace(Sentence, Delimiters[i], ' ', [rfReplaceAll]));
    end;
    i := pos(' ', Sentence);
    while (i > 0) do
    begin
      w := copy(Sentence, 1, i-1);
      sl.Add(w);
      delete(Sentence, 1, i);
      Sentence := Trim(Sentence); // remove duplicate spaces
      i := pos(' ', Sentence);
    end;
    for i := StartCount to EndCount do
    begin
      for j := 0 to pred(sl.count) - pred(i) do
      begin
        w := '';
        for k := j to j + (i-1) do
        begin
          if w <> '' then w := w + ' ';
          w := w + sl[k];
        end;
        words.add(w);
      end;
    end;
  finally
    sl.clear;
    sl.free;
  end;
end;
// --------------- DEMO ------------------

procedure TForm1.Button1Click(Sender: TObject);
begin
  SplitSentence('I am here working with my sister and she is working right now', 1, 2, Memo1.Lines);
end;

hth, Loki
0
 
CynnaCommented:
If I understood right:

procedure SplitSentence2(Sentence: String; SplitNumber: Integer; const Words: TStrings);
var i, j: Integer;
    Delimit: Char;
    w: String;
begin
 Assert(Assigned(Words)); Delimit := ' ';
 with TStringList.Create do try
      Clear; Delimiter := Delimit;
      DelimitedText := Sentence;
      Words.Clear;
      if Count<=SplitNumber then begin
         Words.Add(Sentence); Exit;
      end;
      i:=-1;
      repeat
        Inc(i); w:=Strings[i];
        if i<(Count-1) then begin
           for j:=i+1 to i+SplitNumber-1 do begin
               w:=w+Delimit+Strings[j];
               if j>=(Count-1) then Break;
           end;
        end;
        Words.Add(w);
      until i>=(Count-1);
 finally Free; end;
end;
0
 
2266180Commented:
hi hidrau:

here is the fixed version of your code (had to rewrite a few things :) ):

procedure SplitSentence(Sentence: String; SplitNumber: Integer; const Words: TStrings);
var i, j, k: Integer;
    Delimit: Char;
    w: String;
begin
  Assert(Assigned(Words));
  Words.Clear;
  words.add(sentence);// don't know why, but this is in your example as well
  Delimit := ' ';
  with TStringList.Create do
  try
    Delimiter := Delimit;
    DelimitedText := Sentence;
    for i:=1 to SplitNumber do
      for j:=1 to Count-i+1 do
      begin
        w:=Strings[j-1];
        for k:=j+1 to j+i-1 do
          w:=w+Delimit+Strings[k-1];
        words.add(w);
      end;
  finally
    Free;
  end;
end;

the generation, as I look at it, looks similar to Lokis, but it's a little improved :P
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
TheRealLokiSenior DeveloperCommented:
actually.... mine splits words at other delimiters than space ... so... I think mine is more useful :-P
0
 
2266180Commented:
that is true :P

you could optimize it even more, by not using stringreplace and doing the word parsing from one pass ;)
0
 
hidrauAuthor Commented:
thanks guys.

0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now