Qiang Li
Qiang Li

Reputation: 10865

two questions on string manipulation in Mathematica

  1. Given a character or a string s, generate a result string with n (an integer) repeats of s
  2. Given a list of characters or strings, and a list of the frequencies of their appearance (in correspondence), generate a result string with each string in the list repeated with the desired times as specified in the second list and StringJoin them together. For example, given {"a", "b", "c"} and {1,0,3}, I want to have "accc".

I of course want to have the most efficient way of doing these. Otherwise, my own way is too ugly and slow.

Thank you for your help!

Upvotes: 2

Views: 425

Answers (3)

Mr.Wizard
Mr.Wizard

Reputation: 24336

Knowing your application I propose using Inner:

sets = {{0, 0, 0, 4}, {0, 0, 1, 3}, {0, 1, 0, 3}, {0, 1, 1, 2}, {0, 2, 0, 2},
        {0, 2, 1, 1}, {1, 0, 0, 3}, {1, 0, 1, 2}, {1, 1, 0, 2}, {1, 1, 1, 1},
        {1, 2, 0, 1}, {1, 2, 1, 0}, {2, 0, 0, 2}, {2, 0, 1, 1}, {2, 1, 0, 1},
        {2, 1, 1, 0}, {2, 2, 0, 0}};

chars = {"a", "b", "c", "d"};

Inner[ConstantArray[#2, #] &, sets, chars, StringJoin]
{"dddd", "cddd", "bddd", "bcdd", "bbdd", "bbcd", "addd", "acdd",
"abdd", "abcd", "abbd", "abbc", "aadd", "aacd", "aabd", "aabc", "aabb"}

Upvotes: 2

Verbeia
Verbeia

Reputation: 4420

For 1, Table will do what you need.

s = "samplestring";

  StringJoin[Table[s, {3}]]

  "samplestringsamplestringsamplestring"

But acl's answer using ContantArray is faster, if you care about the last 1/100th second.

Do[StringJoin[Table[s, {30}]];, {10000}] // Timing

{0.05805, Null}

Do[StringJoin[ConstantArray[s, 30]];, {10000}] // Timing

{0.033306, Null}

Do[StringJoin[Table[s, {300}]];, {10000}] // Timing

{0.39411, Null}

Do[StringJoin[ConstantArray[s, 300]];, {10000}] // Timing

{0.163103, Null}

For 2, MapThread will handle cases where the second list is known to be non-negative integers.

StringJoin @ 
 MapThread[Table[#1, {#2}] &, {{"a", "b", "c"} , {1, 0, 3}}]

"accc"

If the second list contains negative integers, these are treated as zeros.

Non-integer elements in the second list are treated as if they are the integer part. I am not sure if this is what you want.

StringJoin @ 
 MapThread[Table[#1, {#2}] &, {{"a", "b", "c"} , {1, 0, 3.7}}]

"accc"

Upvotes: 5

acl
acl

Reputation: 6520

rep[s_String, n_] := StringJoin[ConstantArray[s, n]]

then

rep["f", 3]
(*fff*)

next

chars = {"a", "b", "c"};
freqs = {1, 0, 3};

StringJoin[MapThread[rep, {chars, freqs}]]

gives "accc"

Upvotes: 12

Related Questions