how to iterate correctly through a string with conditionals statements

Hi,

I’m trying to iterate through a string, to trigger events based on the letters of that string:

(var myString, freqA, freqC, freqG, freqT;
myString = "acgaaatga";
myString.do({ arg item;
	freqA = if (item == "a", {66.midicps}, {item.next});
	freqC = if (item == "c", {100.midicps}, {item.next});
	freqG = if (item == "g", {20.midicps}, {item.next});
	freqT = if (item == "t", {45.midicps}, {item.next});
});
freqA.postln;
)

However, the conditions return false each time, and the result of freqA.postln is “g”, the last letter of the string while I hoped to have 369.99442271163. If I replace the false functions item.next, by numbers, it shows these numbers, but only one time. So there is an iteration through the string, but I don’t understand 1) why the condition thrown is false, and 2) why the false condition is only thrown once.

If I replace the == operator by =, it throws a “Non Boolean in test” error. I tried with the case condition, without better results.

Any idea? I would be grateful to understand the logic behind.

Thanks!

String members are characters $a and not strings themselves.

hjh

Oh, thanks!
Do you know why this does not work when the string comes from a FileReader?
Something like this (read a txt from the desktop):

~myData = FileReader.read("/Users/jean-/Desktop/testFileSC.txt");
(var myString, freqA, freqC, freqG, freqT;
myString = ~myData.at(0).asArray.at(0).asString;
myString.do({ arg item;
	freqA = if (item == $a, {66.midicps}, {item.next});
	freqC = if (item == $c, {100.midicps}, {item.next});
	freqG = if (item == $g, {20.midicps}, {item.next});
	freqT = if (item == $t, {45.midicps}, {item.next});
});
freqA.postln;
)

In the post window, this string looks exactly the same as the previous, but all the conditions are thrown false, which puzzle me.

Many thanks!

item == "a" cannot be true if item is the letter a in a string, because in that case, item is $a and not in any way "a".

Your example is still using strings rather than characters for comparison.

hjh

yes, sorry, I copy/paste without correcting that part of the code. it is edited now.

And to be more precise, the false condition is correctly thrown each time the condition is not met, but the true one never appears: I have 9 characters with 5 $a, the false condition is therefore thrown four times.

I’m not sure exactly the output format of FileReader – what do you get if you put an item.postcs inside the loop? Inspect the actual data.

hjh

It gives me the correct list of the characters, ie:

$a
$c
$g
$a
$a
$a
$t
$g
$a
→ acgaaatga

I have re-initiated the global variable ~myData and it’s working fine now.
Thanks!

Hm, do you want to overwrite the freqA variable when the condition is false? I’m suspicious of the formulation freqA = if(...).

And, what do you want to do with these if results within each loop iteration? The current way it’s written means to throw them all away, and look only at the state for the final character (which then probably misleads you into thinking that it never worked).

do is already stepping through the string, so I think item.next is not needed.

I’m not completely clear on your desired result – could you explain a bit more?

(Messages crossed… glad that it’s better.)

hjh

Thanks for your questions, it made me think. I’d like that each letter of a string triggers a specific frequency. So my idea was to iterate through the string and if the letter is ‘a’ then the frequency is 370Hz, if the letter if ‘c’, then the frequency is 2637Hz, etc. Therefore, if the condition is false for the freqA variable, this variable is not overwritten but not used at all. Basically, I wanted freqA to have always the same value and to give that value to an osc when the condition is true.
I now realise that my syntax does not made sense in fact.
I end up with this:

(var myString;
myString = ~myData.at(0).asArray.at(0).asString;
myString.do({ arg item;
	~freq = case
	{item == $a} {~freq = 66.midicps}
	{item == $c} {~freq = 20.midicps}
	{item == $g} {~freq = 110.midicps}
	{item == $t} {~freq = 85.midicps};
	~freq.postln;
});
)

I’m now working to feed an osc with that list of frequencies.