4
$\begingroup$

Given a list of strings:

data = {
 "2894;Hot Pink;53:09:44;1449714",
 "17456;Dark Cyan;19:06:42;6929227",
 "5147;Lime;54:11:55;5247632"
}

(Words are separated by ";", the number of words in strings are equal. Number of characters in strings are unequal. Number of characterss in words are unequal.)

How to extract the $m^{th}$ through $n^{th}$ words, so that e.g. $m=2, n=3$ should return:

{
"Hot Pink;53:09:44",
"Dark Cyan;19:06:42",
"Lime;54:11:55"
}  

UPDATE

Final solution was found for the task.
I like to share it here.

inlist = RandomChoice[
{"7270;Deep Pink;04:14:55;0027354",
 "2871;Dark Orchid;54:21:23;1182263",
 "4021;Silver;04:00:58;6940040",
 "3521;Dark Slate Gray;18:42:43;5828275"}, 
400000];  

delim = ";";
fromWord = 2;
numberOfWords = 2;  

from = 2 fromWord - 1;
to = 2 (fromWord + numberOfWords - 1) - 1;
outlist = List /@ StringJoin /@
      StringSplit[inlist, delim -> delim][[All, from ;; to]]; // Timing  

{0.92, Null}  

The honor goes to the very concerned in this task. Every detail of their conception was vital to the solution. Keep'n rocking.

$\endgroup$
0

4 Answers 4

6
$\begingroup$
f[data_, from_, to_, sep_] := StringSplit[#, sep][[from ;; to]] & /@ data;
data = {"2894;Hot Pink;53:09:44;1449714", 
        "17456;Dark Cyan;19:06:42;6929227", 
        "5147;Lime;54:11:55;5247632"};

f[data, 2, 3, ";"]
(*
->{{"Hot Pink", "53:09:44"}, {"Dark Cyan", "19:06:42"}, {"Lime", "54:11:55"}}
*)
$\endgroup$
7
  • $\begingroup$ @NasserM.Abbasi Of course I can't be sure, but my interpretation comes from the use of the word throughin the OP's sentence Give a list of strings containing chars m'th "Word" through n'th "Word" in elements $\endgroup$ Dec 20, 2012 at 11:41
  • 2
    $\begingroup$ StringSplit is Listable. Try: f[data_, from_, to_, sep_] := StringSplit[data, sep][[All, from ;; to]] $\endgroup$
    – Mr.Wizard
    Dec 20, 2012 at 11:55
  • $\begingroup$ Not quit what is expected. $\endgroup$ Dec 21, 2012 at 11:33
  • $\begingroup$ Will say, not a result with a 3 x 2 element list. It should be a list of 3 elements. The ";" sould be preserved. hp $\endgroup$ Dec 21, 2012 at 11:51
  • $\begingroup$ One could use Take[] instead of Part[]+Span[] of course... $\endgroup$ Apr 4, 2013 at 14:51
4
$\begingroup$

Specific case for $m=2$ and $n=3$:

data = {"2894;Hot Pink;53:09:44;1449714",
        "17456;Dark Cyan;19:06:42;6929227",
        "5147;Lime;54:11:55;5247632"};

First@StringCases[#, 
   StartOfString ~~ __ ~~ ";" ~~ x__ ~~ ";" ~~ y__ ~~ ";" :> x <> ";" <> y] & /@ data
{"Hot Pink;53:09:44", "Dark Cyan;19:06:42", "Lime;54:11:55"}

More general version for any $m, n$:

{m, n} = {2, 3}

StringDrop[StringJoin@Drop[
    StringCases[#, Shortest[__ ~~ ";"], n], m - 1], -1] & /@ data
{"Hot Pink;53:09:44", "Dark Cyan;19:06:42", "Lime;54:11:55"}
$\endgroup$
4
  • $\begingroup$ Your result gives a 3 x 2 list. We need a list of 3 strings. Hot Pink;53:09:44 Dark Cyan;19:06:42 Lime;54:11:55 hp $\endgroup$ Dec 21, 2012 at 11:44
  • $\begingroup$ @HP Please see edit. Nasser: I hope you don't mind that I added the general case to your answer instead of creating a new one. It fits in nicely I think. I you feel otherwise, please don't hesitate to roll back. $\endgroup$ Jan 5, 2013 at 10:21
  • $\begingroup$ OK. . .Your function works well. . .It could not improve in timing compared to the algorithmic one shown below. $\endgroup$ Jan 7, 2013 at 7:56
  • $\begingroup$ Have an other look. It seems not to get the last words. . .If you do {m, n}={1, 4} $\endgroup$ Jan 9, 2013 at 17:01
1
$\begingroup$

A solution was developed. Building a program working on two Streams. One record by one record.

instr = OpenRead[infile];
outstr = OpenAppend[outfile];
azr=3; (* number of records to work on *)
abw=2; (* first word in record to extract *)
azw=2; (* number of words to extract *)
delim=";" (* separator char *)

Do[rean = Read[instr, "Record", NullWords -> True];
arean = rean <> delim;
pos = Flatten[StringPosition[arean, delim]];
fla = Flatten[{0, Drop[pos, {1, Length[pos], 2}]}];
extract = StringTake[arean, {fla[[abw]] + 1, fla[[abw + azw]] - 1}];
WriteString[outstr, extract, "\n"],
{i, azr}]; // Timing

It is a kind of ugly. Could not find a function solution.

$\endgroup$
1
$\begingroup$

Using StringExtract: (introduced March 30, 2015)

data = {"2894;Hot Pink;53:09:44;1449714", 
  "17456;Dark Cyan;19:06:42;6929227", "5147;Lime;54:11:55;5247632"}

StringExtract[#, ";" -> {2, 3}] & /@ data // Map[Riffle[#, ";"] &] // 
 Map[StringJoin]

or

StringExtract[#, ";" -> 2] <> ";" <> 
   StringExtract[#, ";" -> 3] & /@ data

Result

{"Hot Pink;53:09:44", "Dark Cyan;19:06:42", "Lime;54:11:55"}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.