5
$\begingroup$

I have the following list:

l={"1 atattaggtt tttacctacc caggaaaagc caaccaacct
61 ctctaaacga actttaaaat ctgtgtagct gtcgctcggc
121 gcagtataaa caataataaa"}

which I want to turn into:

{{{1,{"atattaggtt","tttacctacc","caggaaaagc","caaccaacct"}},
    {61,{"ctctaaacga","actttaaaat","ctgtgtagct","gtcgctcggc"}},
    {121,{"gcagtataaa","caataataaa"}}}

I wonder how one does this?

Update: I know that StringReplace[l, WhitespaceCharacter -> ","] gives me:

{"1,atattaggtt,tttacctacc,caggaaaagc,caaccaacct,61,ctctaaacga,\
actttaaaat,ctgtgtagct,gtcgctcggc,121,gcagtataaa,caataataaa"}

Yet I don't know how to sublist this as above.

$\endgroup$
3
  • 5
    $\begingroup$ try StringSplit[lis, ","] $\endgroup$
    – Nasser
    Commented Apr 2, 2020 at 19:21
  • 2
    $\begingroup$ @Nasser it was not a simple StringSplit[] $\endgroup$
    – Wiliam
    Commented Apr 2, 2020 at 19:50
  • $\begingroup$ I was replying to what you said Yet I don't know how to sublist this as above. not to the main question. $\endgroup$
    – Nasser
    Commented Apr 2, 2020 at 19:55

9 Answers 9

8
$\begingroup$

You may use StringCases with StringExpression.

StringCases[
  n : NumberString ~~ s : (WhitespaceCharacter ~~ LetterCharacter ..) .. :> 
    {FromDigits@n, StringSplit@s}
]@l
{{{1, {"atattaggtt", "tttacctacc", "caggaaaagc", "caaccaacct"}}, 
  {61, {"ctctaaacga", "actttaaaat", "ctgtgtagct", "gtcgctcggc"}}, 
  {121, {"gcagtataaa", "caataataaa"}}}} 

Hope this helps.

$\endgroup$
9
$\begingroup$
{First[#], Rest[#]} & /@ ImportString[#, "Table"] & /@ l

(*    {{{1, {"atattaggtt", "tttacctacc", "caggaaaagc", "caaccaacct"}},
        {61, {"ctctaaacga", "actttaaaat", "ctgtgtagct", "gtcgctcggc"}},
        {121, {"gcagtataaa", "caataataaa"}}}}                              *)
$\endgroup$
5
$\begingroup$

Another way using regular expressions.

StringSplit[l, RegularExpression["(?=[A-Z]|(?<!\\d)\\d)"]] // 
  Map[StringSplit /* ({First@#, Rest@#} &), #, {-1}] &
$\endgroup$
4
$\begingroup$
StringCases[l,
  RegularExpression["([1-9]+)([a-t\s]+)"]:> {"$1", StringSplit["$2"]}
]

{{{1, {atattaggtt, tttacctacc, caggaaaagc, caaccaacct}}, {61, {ctctaaacga, actttaaaat, ctgtgtagct, gtcgctcggc}}, {121, {gcagtataaa, caataataaa}}}}

Original Answer

StringCases[l,RegularExpression["([1-9]+)([a-z\s]+)"]:> {"$1", "$2"}]
  // MapAt[StringSplit, #, {All,All,2}]&
$\endgroup$
3
$\begingroup$
Map[{FromDigits @ #, {##2}} & @@@ # & @* StringSplit] @ StringSplit[l, "\n"]
{{{1, {"atattaggtt", "tttacctacc", "caggaaaagc", "caaccaacct"}}, 
  {61, {"ctctaaacga", "actttaaaat", "ctgtgtagct", "gtcgctcggc"}},
  {121, {"gcagtataaa", "caataataaa"}}}}

Also

f = Normal[{#, DeleteCases[{##2}, ""]} & @@@ SemanticImportString[#]] &;
f /@ l
{{{1, {"atattaggtt", "tttacctacc", "caggaaaagc", "caaccaacct"}}, 
  {61, {"ctctaaacga", "actttaaaat", "ctgtgtagct", "gtcgctcggc"}}, 
  {121, {"gcagtataaa", "caataataaa"}}}}

and

f2 = {FromDigits @ #, {##2}} & @@@ 
      Split[StringSplit @ #, Not @* StringMatchQ[NumberString] @* First] &;
f2 /@ l
 {{{1, {"atattaggtt", "tttacctacc", "caggaaaagc", "caaccaacct"}},
   {61, {"ctctaaacga", "actttaaaat", "ctgtgtagct", "gtcgctcggc"}},
   {121, {"gcagtataaa", "caataataaa"}}}}
$\endgroup$
3
$\begingroup$
list = {
 "1 atattaggtt tttacctacc caggaaaagc caaccaacct
 61 ctctaaacga actttaaaat ctgtgtagct gtcgctcggc
 121 gcagtataaa caataataaa"};

Using SequenceSplit (new in 11.3)

{SequenceSplit[
  ToExpression @ First @ StringSplit @ list,
  {a_, b__Symbol} :> {a, ToString /@ {b}}]}

{{{1, {"atattaggtt", "tttacctacc", "caggaaaagc", "caaccaacct"}}, {61, {"ctctaaacga", "actttaaaat", "ctgtgtagct", "gtcgctcggc"}}, {121, {"gcagtataaa", "caataataaa"}}}}

$\endgroup$
3
$\begingroup$
list = {
 "1 atattaggtt tttacctacc caggaaaagc caaccaacct
 61 ctctaaacga actttaaaat ctgtgtagct gtcgctcggc
 121 gcagtataaa caataataaa"};

Following @eldo's idea, an equivalent form using SequenceCases:

{SequenceCases[
 ToExpression@First@StringSplit@list,
 {a_, b__Symbol} :> {a, ToString /@ {b}}]}

{{{1, {"atattaggtt", "tttacctacc", "caggaaaagc", "caaccaacct"}}, {61, {"ctctaaacga", "actttaaaat", "ctgtgtagct", "gtcgctcggc"}}, {121, {"gcagtataaa", "caataataaa"}}}}

$\endgroup$
2
$\begingroup$

So after playing a bit, I found the solution:

x0 = StringSplit[l, Whitespace] // Flatten // ToExpression;
x1 = Split[x0, ! IntegerQ[#2] &];
x2 = Map[Drop[#, 1] &, x1];
x3 = Table[Map[ToString[#] &, x2[[i]]], {i, Length[x2]}];
x4 = Map[Take[#, 1] &, x1] // Flatten;
final = Transpose[{x4, x3}]

To which I get:

{{1, {"atattaggtt", "tttacctacc", "caggaaaagc", 
   "caaccaacct"}}, {61, {"ctctaaacga", "actttaaaat", "ctgtgtagct", 
   "gtcgctcggc"}}, {121, {"gcagtataaa", "caataataaa"}}}

As desired. Maybe you guys can make this more efficient.

$\endgroup$
1
  • 1
    $\begingroup$ Your 'as desired' differs somewhat to that given in your question $\endgroup$
    – user1066
    Commented Apr 2, 2020 at 22:13
2
$\begingroup$
l = {"1 atattaggtt tttacctacc caggaaaagc caaccaacct
61 ctctaaacga actttaaaat ctgtgtagct gtcgctcggc
121 gcagtataaa caataataaa"};

res = {First@l // StringSplit // 
    Split[#, ! StringMatchQ[#2, NumberString] &] & // 
   MapAt[ToExpression, {All, 1}]}

{{{1, "atattaggtt", "tttacctacc", "caggaaaagc", "caaccaacct"}, {61,
"ctctaaacga", "actttaaaat", "ctgtgtagct", "gtcgctcggc"}, {121,
"gcagtataaa", "caataataaa"}}}

$\endgroup$

Your Answer

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

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